Chapter 1
char *cp;
const char *ccp;
ccp = cp;
ccp是有指向有const 限定符的char 的指针,cp是指向没有限定符修饰的指针;左操作数具有右操作数的所有限定符(空),再加上自身的限定符(const);但是反过来赋值cp = ccp 就会违反赋值约束条件,就会产生编译告
警。
const float * 是指向具有const限定符的float类型的指针,也就是说const限定符是修饰指针所指向的类型,而不是指针本身。类似的,const char ** 也不是具有限定符的类型,它是指向有const 限定符的
float类型的指针的指针,也就是说const 限定符是修饰指针的指针所指向的类型;char ** 类型指向char *,
const char **类型指向const char * 两者是不相容的。
const 并不能把变量变成常量,在一个符号前面加上const 限定符只是表示这个符号不能被赋值,但也不能防止
通过程序的内部方法来修改这个值,const 最有用之处就是用它来限定函数的形参,这样该函数将不会修改实参指针所指的数据,但其他的函数却可能会修改它,这是const最一般的用法。
const int limit = 10;
const int * limitp = &limit;
int i = 27;
limitp = &i;
这段代码表示limitp是一个指向常量整形的指针,也就是说const 是修饰limitp指针指向的int类型。这个指针
不能用于修改被指向的int类型,但是任何时候limitp本身的值却可以改变。这样limitp就指向了不同的地址。
const int * a与 int const * a两者没有区别;int * const a 与前两者不同,表示指针a的值不能修改
即a指向地址不能修改,但是可以修改a指向地址的内容;前两者表示不能通过指针a修改a所指向的内容,但是a
可以指向其他地址;---参考链接:https://www.cnblogs.com/wecode/p/6146739.html
有符号数二进制原码,正数,最高位符号位是0,其余部分是数值位;负数,最高位符号位是1,其余部分是数值位;
有符号数二进制补码,正数的补码就是二进制原码,负数的补码是二进制反码加1;
有符号数SWORD16的最大值是0x7FFF,第一位拿来当做符号位;
有符号数的二进制反码,正数的反码与二进制原码相同,负数的二进制反码是二进制原码除符号位外按位取反;
有符号数转换成无符号数,有符号正数原码就是无符号正数原码,有符号负数二进制原码的补码就是转换成的无符号数;
无符号数转换成有符号数,最高位不为1,无符号数的原码就是有符号数的原码,最高位为1,将此无符号数的原码视为有符号数的原码,除最高位即符号位负号外,最低7位作为数值位;
补码=>原码,符号位0 补码就是原码;符号位1 ,其余位取反后加1 是原码
Chapter2
//一种简单的方法,使一段代码第一次执行时的行为与以后的执行时不同
generate_initializer(char * string)
{
static char separator = ' ';
printf("%c %s \n", seperator, string);
separator = ',';
}
static function turnip() {} //static 声明表示在这个文件之外不可见
static 在函数内部,表示该变量的值在各个调用间一直保持延续性;
extern 用于函数定义,表示全局可见(属于冗余),用于变量表示它在其他地方定义;
void 作为函数的返回类型表示不反悔任何值,在指针的申声明中表示通用指针的类型,位于参数列表中表示没有参数;
sizeof操作数是类型时两边必须加上括号,但操作数如果是变量则不必加括号;
优先级问题 | 表达式 | 可能误以为的结果 | 实际结果 |
.的优先级高于*; ->操作符用于消除这个问题 |
*p.f | p所指向对象的f字段 | 对p取f偏移,作为指针,然后进行解除引用操作,*(p.f) |
[]高于* | int *ap[] | ap是个指向int数组的指针int(*ap)[] | ap是个元素为int指针的数组 int* (ap[]) |
函数()高于* | int *fp() | fp是个函数指针,所值函数返回int | fp是个函数,返回int* ,int*(fp()) |
== 和!=高于位操作符 | (val & mask != 0) | (val & mask) != 0 | val &(mask != 0) |
== 和!= 高于赋值符 | c = getchar() != EOF |
(c = getchar()) != EOF | c = (getchar() != EOF) |
算术运算符高于移位运算符 | msb << 4 + lsb | (msb << 4) + lsb | msb << (4 + lsb) |
逗号运算符在所有运算符中优先级最低 | i = 1,2 | i = (1,2) | (i = 1),2 |
针对最后一行,当执行
i = 1,2;
赋值最运算符优先级高于逗号,i 应该是1,但是实际上i 赋值为1,接着执行常量2的运算,计算结果将丢弃.
最终i的结果是1而不是2.
在if 和while 等后面需要一个布尔值的时候,& 和 |就被翻译成&& 和 || ;如果在一般的表达式里,就被解释成位操作符。
操作符的结合性,在几个操作符具有相同优先级时决定先执行哪一个,赋值运算符具有右结合性,位操作符 & 和 | 具有左结合性。
/* 将源文件的timestamp转换为表示当地格式日期的字符串 */
char * localized_time(char * filename)
{
struct tm *tm_ptr;
struct stat stat_block;
char buffer[120];
/* 获得源文件的timestamp, 格式为time_t */
stat(filename, &stat_block);
/* 把UNIX的time_t转换为tm结构,里面保存当地时间 */
tm_ptr = localtime(&stat_block.st_mttime);
/* 把tm结构转换成以当地日期格式表示的字符串 */
strftime(buffe