c语言查漏补缺
c语言查漏补缺结构体对齐编译器对齐 4字节, int以下集中对齐鲲鹏优化时候,字节对齐会影响原子操作 coredumpNUMA 优化 (鲲鹏处理器优化)socket 里面有多个 core, 鲲鹏2个core算一个NUMA node(逻辑概念), 一个node分配一些资源(4个DDR通道)设置网卡中断的cpu亲和性,减少跨 NUMA core产生的额外开销echo c...
c语言查漏补缺
-
结构体对齐
- 编译器对齐 4字节, int以下集中对齐
- 鲲鹏优化时候,字节对齐会影响原子操作 coredump
-
NUMA 优化 (鲲鹏处理器优化)
socket 里面有多个 core, 鲲鹏2个core算一个NUMA node(逻辑概念), 一个node分配一些资源(4个DDR通道)
-
设置网卡中断的cpu亲和性,减少跨 NUMA core产生的额外开销
echo c p u M a s k > / p r o c / i r q / cpuMask > /proc/irq/ cpuMask>/proc/irq/irq/smp_affinity_list
-
numactl 可以指定程序运行的内核位置
numactl -C 28-31 ./test
-
C/C++代码中通过 sched_setaffinity 函数来设置线程亲和性
-
软件设置
-
-
CacheLine优化(鲲鹏处理器优化)
将 频繁写的变量(锁)声明为 CacheLine对齐
-
指针篇
-
指针有三个属性: 类型, 名称, 值
-
指针操作有 赋值 和 加
指针变量 + 数字 = 指针变量值 + 数字 * sizeof(指向类型)
-
数组名 和 指针
-
举例子
int a[10],*p=a;
-
数组名称
a
相当于地址常量, 那么这个地址指向一段内存, 因此这个地址本身会有指向类型, 其指向类型就是数组的元素类型. 例如int a[10]
, 那么a
的 指向类型 就是int, 即a, p
操作等价**. -
&a
的指针值和a
的指针 值 一样, 而且也是个地址常量, -
数组的
sizeof
值等于数组所占用的内存字节数,sizeof(a)
是计算整个数组的类型,40sizeof(*a)
是计算a指向类型的大小,即 int,4&a
的指向类型是int(*) [10]
, 即指向一个包含10个int元素的数组指针,行指针, 所以sizeof(&a)
, 计算&a
的指向类型的占用内存大小就是40. -
数组作为函数参数传递后, 在函数内使用等价于指针. 因为函数传参是进行值传递, 相当于有一个指针变量记录数组的地址值.
-
-
函数指针
-
对函数名本身计算类型占用内存大小, 其值为1, 对于函数名的指向类型计算内存占用大小其值也为1.
-
foo, *foo, &foo的类型相同, 但是sizeof(&foo)结果为8.
-
函数指针可以进行多次解引用, *****p_foo == *p_foo = p_foo.
-
函数指针可以进行调用, p_foo(3);
以上几点可以认为是函数的特殊情形, 直接记忆.
可以将函数的指令看作是一个unsigned char []的数组. 这样函数名就好像是一个数组名一样, 都是地址常量, 其指向类型为unsigned char类型. 但是函数指令的数组的长度是未知的, 因此编译器默认输出sizeof(foo)为1, sizeof(*foo)相当于是sizeof(unsigned char)为1.
-
-
expample
-
#include <stdio.h>
// different between a and &a;
int main (void)
{
printf("hello\r\n");
int q[4]={1,2,3};
int a[4]={1,2,3};// This is where we will began.
int b[4]={1,2,3};
printf("%d %d\r\n",a[1],*(a+1));
printf("%d %d\r\n",a,&a);
printf("%d %d\r\n",(a+1),(&a+1));
printf("%d %d %d\r\n",q,*(&a+1),**(&a+1));
}
用 TinyC 运行(ArmC6同样运行通过)
$ tcc -run test.c #变量有3个要素,名字、类型和数值,a和&a
hello
2 2 # a[1],*(a+1) 结果一致,也就是民间传言的,a和&a,指针和数组名一致
6486732 6486732 # 开始验证 a 和 &a,数值相同
6486736 6486748 # 继续验证,运算规则不同,说明类型不同
6486748 6486748 1 # 经过尝试,理解语法,我怀疑&a是一个数组指针 int(*)[4] 类型,指着0号位
我们用二维数组 和 数组指针(行指针)来说明下问题。
#include <stdio.h>
//
int main (void)
{
printf("hello\r\n");
int q[4]={1,2,3};
int a[4][2]={1,2,3};// This is where we will began.
int b[4]={1,2,3};
printf("%d %d %d\r\n",a[1],*(a+1),(*(a+1)+0));
printf("%d %d %d\r\n",*(*(a+1)+0),*(a[1]+0),a[1][0]);
printf("%d %d %d\r\n",b,&a+1,(*(&a+1))[1][0]);
//--------vertify the conjecture now -----
printf("-----------------------------------------------\r\n");
int (*p)[2]=a+1;//注意*[]的优先级,这里定义了行指针、数组指针。int *p[2] 是指针数组的定义。双重指针 和 指针数组的定义方式 不同于 二维数组。
p = a+0;
printf("%d %d %d\r\n",p[1][0],**(p+1),a[1][0]);
p = &q;
printf("%d %d %d\r\n",p[0][1],*(p[0]+1),q[1]);
}
来看一下,分析一下结果
$ tcc -run test.c
hello
6486724 6486724 6486724 #复习常见的二维数组操作
3 3 3
6486700 6486748 3 # 同理,此处&a 不是行指针,而是更高的数组指针int (*)[4][2]
-----------------------------------------------
3 3 3 #&q and a都是行指针类型 int(*)[]
2 2 2 #此处验证一下,一维数组q可以用数组指针来操作,只要保证第零行就行
参考链接
更多推荐
所有评论(0)