C
char * q = &ch;
*q = 'C';
printf("%c\n", ch);
结果输出C,只不过有类型兼容警告。声明为const只不过是希望程序不要(通过该名字)修改它,只读即可,但其值可能被(其它指向该变量的引用)修改,比如用来修饰硬件寄存器的值。
char a[4]="abcd";
const char *s = a;
a[0] = 'b';
//*s = 'a';//error另外,如果const修饰初始化的字符串(如const char *s="string";),则该字符串实际存在于文本段,文本段一般是只读和可执行的,所以任何对它的修改都可能导致段错误。
char a[]="abcd";
char *s ="abcd";
sizeof(a)=5,sizeof(s)=4,a[]包含了字符串的结束符'\0',除非制定它的大小。如果指定了大小比如a[4],但字符数超过了该大小,则编译器一般会自动截断并发出警告。说到const就不能不提volatile,参见http://superding.spaces.live.com/blog/cns!89E842A8485366C7!1019.entry。
2、大小端。内存地址从低到高的方向,一个整数从高字节开始存放就是大端(高大低小)。
0x0001存放于地址0x0-0, 0x1-0, 0x2-0, 0x3-1就是大尾端。
堆栈溢出,http://www.stmcu.org/myspace/blog/show.php?id=167317。
内存地址对齐,http://blog.csdn.net/reiskie/archive/2007/06/11/1647605.aspx。
3、见过长这样的数组?int a[5], *p=a; 2[a]=1; printf("%d\n", 2[p]);反正编译后都等于*(a+2)或*(2+p),不在乎多么奇怪的写法,比如继续写int i=2; i=i[a];不过让人看到这种代码肯定会让人头疼死的。 a[0]=({p[1]=2;});*({p+1;})=7;*(p=a)=0; 这些都是正确的语法,但多此一举。更过分的是*({int tmp;p=&tmp;})=3;恐怕p会成为野指针了。见怪不怪,只是为了理解
const typeof(((type *)0)->member) * __mptr = (ptr); \
(type *)((char *)__mptr - offsetof(type, member)); })
4. i = i++ + j;问题,即是先计算本表达式还是先完成自增运算。这是一个无聊的问题,这有SB才会这样写代码,可是偏偏有很多公司会问这样的问题。
i = i++ + j;
在Linux上gcc编译运行的结果是2。
i = i++;
结果是0。没有任何解释,看汇编代码就知道了,-S选项,第一段汇编代码:
movl $0, -4(%rbp)
movl $1, -8(%rbp)
movl -4(%rbp), %eax
addl -8(%rbp), %eax /* 先完成了i+j的计算 */
movl %eax, -4(%rbp) /* 结果写回给i */
leaq -4(%rbp), %rax /* i的地址 */
incl (%rax) /* 计算i++,可见表达式计算完成之后才自增 */
movl $0, %eax
leave
ret
第二段汇编代码:
movl $0, -4(%rbp) /*相当于把立即数0赋给i*/
movl -4(%rbp), %eax /*取i的值放入寄存器eax中*/
leaq -4(%rbp), %rdx /*传i的地址给寄存器rdx*/
incl (%rdx) /*该地址的内容增1*/
movl %eax, -4(%rbp) /*将eax的值写回i,可见这里是完成了自增操作之后再赋值的*/
movl $0, %eax
leave
ret
对于这样的计算顺序是否有规范不得而知,不然就看编译器实现吧。在其他语言中,对以上两例,PHP和Java得出的结果是1和0。


浙公网安备 33010602011771号