小组面试题2017笔记
来自第1题
关于sizeof
sizeof :不可拓展关键字,求对象所占字节大小。
strlen :函数,求字符串的长度(以’/0’结束)。
sizeof(指针); //指针变量在内存中所占长度 (1)
strlen(指针); //指针指向的字符串的长度
sizeof(数组名); //数组所占的长度 (2)
sizeof(*指针); //指针指向的对象占字节大小
//由(1)(2)可知指针与数组名的区别就是在sizeof上的不同,除此之外指针是变量可以改变,而数组名不同
此外还要注意,sizeof在编译时就进行了操作,只获取对象类型然后替换,并未对里面的代码进行其他操作。
int t=4;
sizeof(t--)//只获取t的类型,并未对t进行运算,所以t的值为4不变;
来自第2题
关于printf函数
printf的传入参数可变,并从右向左执行(相当于栈结构,左往右入栈,右往左出栈,再运算)
printf的返回值为输出字符所占列宽,如果异常则返回负数
来自第3题
void get_str(char *ptr)
{
ptr = (char*)malloc(17);
strcpy(ptr, "Xiyou Linux Group");
}
int main(int argc, char *argv[])
{
char *str = NULL;
get_str(str);
printf("%s\n", str);
}
以上代码str指针在传入get_str函数后ptr又指向了新的内存,所以主函数输出的str还是NULL;
这个改法很多,最方便最有逼格的改法……使用二级指针…
void get_str(char **ptr)
{
*ptr = (char*)malloc(18);
strcpy(ptr, "Xiyou Linux Group");
}
int main(int argc, char *argv[])
{
char *str = NULL;
get_str(&str);
printf("%s\n", str);
}
来自第4题
这道题需要扯清楚函数指针,指针函数。然后在扯清楚以函数指针作为返回值,传入值,再扯清楚函数指针数组,最后能把以上内容结合在一起就大成了…
在这里偷个懒,推荐这个博讲的很详细——>http://hipercomer.blog.51cto.com/4415661/792300
而本题关节之处就是在size_t(*p(char *str))(size_t a)这是一个返回值为函数指针的函数,
(p(char *str))为函数指针,其传入值为(char *str),返回值为size_t *size_t a))型的函数指针.
size_t q(size_t b)
{
return b;
}
size_t (*p(char *str))(size_t a)
{
printf("%s\n", str);
return q;
}
int main(int argc, char *argv[])
{
char str[] = "XiyouLinuxGroup";
printf("%lu\n", p(str)(strlen(str)));
return 0;
}
来自第8and19题
从原文件,到可执行文件:
。。。 | 预处理 | 编译 | 汇编 | 链接 |
---|---|---|---|---|
Linux命令 | gcc -E 或cpp > | gcc -S | gcc -c或者as | ld |
生成文件 | .i | .s | .o | .a.out(linux) .exe(Win) |
1.预处理:对宏定义,文件包含,条件编译(#ifdef #difine #”.h”)进行处理
2.编译
预编译———-词法分析,语法分析;
中间代码
优化————-对空格,部分语句优化;
汇编代码
3.汇编:生成计算机可识别的 0 1 代码,有各个段(代码段,数据段…)
4.链接:将所有需要的文件链接在一起,形成可执行文件。
(再偷个懒……)关于C程序编译过程详细—->http://blog.csdn.net/koudaidai/article/details/8092647
来自第12题
stdout:有换行缓存,读完一个/n才输出;
stderr:错误输出,马上输出,没有缓存;
在默认情况下,stdout是行缓冲的,他的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。而stderr是无缓冲的,会直接输出,举例来说就是fprintf(stdout, “xxxx”) 和 fprintf(stdout,”xxxx\n”),前者会缓存,直到遇到新行才会一起输出。而fprintf(stderr, “xxxxx”),不管有么有\n,都输出。
int main(int argc, char *argv[])
{
while(1)
{
fprintf(stdout, "Group ");
fprintf(stderr, "XiyouLinux");
getchar();
}
return 0;
}
至于本题我们还需要知道键盘缓冲区这个东西,就是说你在键盘敲入的字符会存在键盘缓冲区里,当缓存区刷新的时候程序才会开始对你输入的数据流进行使用。(键盘缓冲区刷新在缓存区满了,或者遇到’\n’,或者程序结束时)如图:
当输入123’\n’后键盘缓冲区将其记录下来,遇到’\n’开始刷新,(程序开始使用数据)
1被getchar();读入
循环到了fprintf(stdout, “Group “);stdout有缓存,所以字符Group存在了buffer里面;
继续到下一句fprintf(stderr, “XiyouLinux”);stderr没有缓存,XiyouLinux输出到屏幕上;
2被getchar();读入
.
.
.
‘\n’被getchar();读入
循环到了fprintf(stdout, “Group “);stdout有缓存,所以字符Group存在了buffer里面;(上面讲了遇到新行才输出)
继续到下一句fprintf(stderr, “XiyouLinux”);stderr没有缓存,XiyouLinux输出到屏幕上;
‘\n’读入结束,到新行,buffer里面存的字符打印出来
所以有4个XiyouLinux四个Group
来自第13题
int main(int argc, char *argv[])
{
char str[512];
int i;
for (i = 0; i < 512; ++i)
{
str[i] = -1 - i;//赋值时将int型赋给char型,只赋低字节位数所以只考虑最低位
}
printf("%lu\n", strlen(str));
return 0;
}
-1补码1…………1111 1111,每次减一
1 补码0…………0000 0001,减到512时为
补码为1………1 0000 0000,所以str[512]为第一个’\0’
所以strlen(str)为512;
来自第14题
要使得交换两个数的类型无限制,使用泛型法。对字节进行复制。
void swap(void* x, void* y,int size)
{
void* tmp=malloc(size);
memcpy(tmp, x, size);
memcpy(x, y, size);
memcpy(y, tmp, size);
free(tmp);
}
int main()
{
int x=10;
int y=5;
swap(&x,&y,sizeof(x));
printf("%d %d",x,y);
return 0;
}
来自第17题
这个首先要知道一点就是大部分计算机存储时低位在前,神么意思呢…?
比如一个int a=666; 666=1010011010(2进制)
7的补码 | 0000 0000 | 0000 0000 | 0000 0010 | 1001 1010 |
---|---|---|---|---|
字节位数 | 第4位 | 第3位 | 第2位 | 第1位 |
而在大部分计算计内存中它的储存方式为低位在低地址,所以
1001 1010
0000 0010
0000 0000
0000 0000
struct node
{
char a;
short b;
int c;
};
int main(int argc, char *argv[])
{
struct node s;
memset(&s, 0, sizeof(s));
s.a = 3;
s.b = 5;
s.c = 7;
struct node *pt = &s;
printf("%d\n", *(int*)pt);
printf("%lld\n", *(long long *)pt);
return 0;
}
然后我们要知道,为提高CPU存储变量的速度,在读取内存数据时会连着几位一起读。32位的CPU内存以4字节,64位的CPU的以8字节。结构体在储存时为方便以上规律就会自动对齐。
所以char占两个字节(地位存a,高位空着),short占两个,int占四个;
所以a=3,b=5,c=7;在内存中储存方式如下(注意低位在前)
0000 0011(char a = 3)
0000 0000 (字节对齐问题空一排)
0000 0101(short b=5;两个字节)
0000 0000
0000 0111(int c=7;四个字节)
0000 0000
0000 0000
0000 0000
接下来就是强制转化的问题了,强制转化为int型,所以就读四个字节
0000 0000 0101 0000 0000 0000 0011(转化为十进制为327683)
再强制转化为longlong类型,读八个字节
0000 0000 0000 0000 0000 0000 0000 0111 0000 0000 0000 0101 0000 0000 0000 0011(转化为十进制为30065098755)
————————————————————————假装我是分割线—————————————————————————
第一篇博客…如果有大神发现有问题尽情留言纠正…
有哪里看不明白的小伙伴也可以留言~~~
拜~~