c lang misc
补码
正数的补码就是其本身
负数的补码就是在其原码的基础上,符号位不变,取反后加一。
补码存在的意义就是为了统一计算机加减
比如(7)+(-7)=0
7 -> 0000 0111(7的补码)
-7 -> 1111 1001(-7的补码)
所以相加为1 0000 0000(超出的最高位默认去掉)
比如(2)+(-3)=(-1)
2 -> 0000 0010 (2的补码)
-3 -> 1111 1101 (-3的补码)
相加为 1111 1111(-1的补码)
这样我们就可以在减法运算的时候,把数化为补码进行计算,这样就在计算时统一了加减。
from:
https://www.cnblogs.com/QKSword/p/8149053.html
C volatile指针以及volatile指向的对象
一般说来,volatile用在如下的几个地方:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile;
2、多任务环境下各任务间共享的标志应该加volatile;
3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义;
volatile修饰指针一般用在共享指针上面。
下面代码:
uchar * volatile reg;
行代码里volatile修饰的是reg这个变量。所以这里实际上是定义了一个uchar类型的指针,并且这个指针变量本身是volatile 的。但是指针所指的内容并不是volatile的!在实际使用的时候,编译器对代码中指针变量reg本身的操作不会进行优化,但是对reg所指的内容 reg却会作为non-volatile内容处理,对reg的操作还是会被优化。通常这种写法一般用在对共享指针的声明上,即这个指针变量有可能会被中断等函数修改。将其定义为volatile以后,编译器每次取指针变量的值的时候都会从内存中载入,这样即使这个变量已经被别的程序修改了当前函数用的时候也能得到修改后的值(否则通常只在函数开始取一次放在寄存器里,以后就一直使用寄存器内的副本)。
需要注意将上述代码与下面的代码进行区别
这行代码里volatile修饰的是指针所指的内容。所以这里定义了一个uchar类型的指针,并且这个指针指向的是一个volatile的对象。但是指针变量本身并不是volatile的。如果对指针变量reg本身进行计算或者赋值等操作,是可能会被编译器优化的。但是对reg所指向的内容 reg的引用却禁止编译器优化。因为这个指针所指的是一个volatile的对象,所以编译器必须保证对reg的操作都不被优化。通常在驱动程序的开发中,对硬件寄存器指针的定义,都应该采用这种形式。
而
volatile uchar * volatile reg;
这样定义出来的指针就本身是个volatile的变量,又指向了volatile的数据内容。
from:
https://www.wenjiangs.com/group/topic-9867.html
打印格式输出符中的#
区分不同进制数字的一个简单办法就是,在输出时带上特定的前缀。在格式控制符中加上#
即可输出前缀,例如 %#x、%#o、%#lX、%#ho 等,请看下面的代码:
#include <stdio.h> int main() { short a = 0b1010110; //二进制数字 int b = 02713; //八进制数字 long c = 0X1DAB83; //十六进制数字 printf("a=%#ho, b=%#o, c=%#lo ", a, b, c); //以八进制形似输出 printf("a=%hd, b=%d, c=%ld ", a, b, c); //以十进制形式输出 printf("a=%#hx, b=%#x, c=%#lx ", a, b, c); //以十六进制形式输出(字母小写) printf("a=%#hX, b=%#X, c=%#lX ", a, b, c); //以十六进制形式输出(字母大写) return 0; }
运行结果:
a=0126, b=02713, c=07325603
a=86, b=1483, c=1944451
a=0x56, b=0x5cb, c=0x1dab83
a=0X56, b=0X5CB, c=0X1DAB83
from:
http://c.biancheng.net/cpp/html/3421.html
void *指针算术运算
int a = 10; void *test_ptr = (void*)&a; printf("test_ptr is: 0x%p. ", test_ptr); printf("test_ptr + 4 is: 0x%p. ", test_ptr+4);
执行结果如下:
test_ptr is: 0x0x7fffbcd844a4. test_ptr + 4 is: 0x0x7fffbcd844a8.
可知void *指针加1实际也只加1
unsigned类型打印格式符
在您尝试的所有组合中, %ld
和%lu
是唯一有效的printf格式说明符。 %lu
(长无符号十进制), %lx
或%lX
(带有小写或大写字母的长十六进制)和%lo
(长八进制)是unsigned long类型变量的唯一有效格式说明符(当然,您可以添加字段%
和l
之间的宽度,精度等修饰符。
printk一些技巧
https://www.cnblogs.com/sky-heaven/p/7161373.html
%*d
此打印格式是为了让输出结果占满指定的宽度,比如如下这段表示%*d输出宽度占6个character,所以结果为....30,这里的一个点表示一个空格:
int a = 6;
int b = 30;
printf("b value: %*d. ", a, b);