C-技巧积累

目标文件中使用的地址

目标文件在链接之前, 其使用的地址都是相对地址 (或未重定向的地址):

  • 起始位置为 0 开始 (真实地址是链接后加上一个地址)

这些相对地址记录在目标文件的符号表中.

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

void foo() {
printf("In foo\n");
}

void bar() {
printf("In bar\n");
}

int main() {
foo();
bar();
return 0;
}

假设目标文件中的地址为:

函数名 相对地址
foo 0
bar 16
main 32

(这里函数的长度先不管)

则链接后, 连接器会将其转换为绝对地址, 加入是被加载到内存中的 0x1000 处, 则为:

函数名 链接后的地址
foo 0x1000
bar 0x1000 + 16
main 0x1000 + 32

一般在调用时会动态链接, 此时才会决定在内存中的位置.

main 函数是否有函数声明

因为 main 是程序的入口点, 编译器会自动识别其定义而不需要额外的函数声明.

函数声明的简写

在函数声明中, 函数的参数名一般不太重要, 直接写类型即可, 如:

1
void process_data(int, int);

变长数组

也就是说数组的长度可以由一个变量值来确定了. 如:

1
2
3
4
5
6
7
#include <stdio.h>

int main(void) {
int n = 10;
int arr[n];
printf("%ld", sizeof(arr)/sizeof(arr[0]));
}

生成随机数

若不设置种子, rand() 只是伪随机数 (即每次运行返回的都一样).

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
// 设置随机数种子
srand((unsigned)time(NULL));

// 生成并打印 10 个随机数
for (int i = 0; i < 10; i++) {
int random_number = rand(); // 生成随机数
printf("随机数 %d: %d\n", i + 1, random_number);
}

return 0;
}
  • srand((unsigned)time(NULL)), 这里的 (unsigned) 是强制类型转换, time(NULL) 获取当前时间

定义和使用二进制数

0b 前缀. 如:

1
2
3
4
5
6
7
#include <stdio.h>

int main(void) {
int bin = 0b10011;
int result = 0b10011 & 0b11111;
printf("Result: %d", result);
}

C-技巧积累
http://example.com/2024/09/25/C-技巧积累/
作者
Jie
发布于
2024年9月25日
许可协议