文章目录
前言
记录工作学习中遇到一些C/C++编程技巧,目前还在不断完善中。。
1、 C语言宏定义中#符号和##的妙用
- #运算符用在预编译时期,用于将宏参数转换为字符串,即是加上双引号。
- ##运算符用于在预编译期粘连两个符号,增大了宏的使用灵活性!
#define Str(a) #a
#define Compliant(a,b) Str(a##b)
// 错误示例:不能在同一个宏定义中同时使用#和##
// #define NonCompliant(a, b) # a ## b
int main() {
cout << Str(World) << endl;
cout << Compliant(Hello,World) << endl;
}
World
HelloWorld
2、变长结构体
当结构体中含有字符指针时,使用边长结构体可以方便申请/释放内存。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdlib.h>
#define PATH_LENG 10
struct Stu {
int a;
char name[1];
};
int main(int argc, char **argv) {
int len = strlen(name);
struct Stu *stu = (struct Stu*)malloc(sizeof(struct Stu) + 9);
char *name = "123456789";
memcpy(stu->name, name, sizeof(name));
printf("%s %d\n", stu->name, sizeof(name));
return;
}
3、sizeof和strlen的区别
sizeof()
用于计算变量或类型所占字节数strlen()
用于计算字符串中字符个数(不包括字符串结尾的空字符 ‘\0’)
void func(char *a){
printf("%d %d\n",sizeof(a), strlen(a));
}
int main() {
char str[50] = "12345";
printf("%d %d\n",sizeof(str), strlen(str));
func(str);
}
50 5
8 5
在main函数中sizeof统计的是字符数组的大小,而在func中统计的则是指针的大小,64位平台下,一个指针的大小是8字节。
4、字符串初始化与数组越界问题
4.1 字符串会被默认的加上结束符’\0’。
char d[4] = "abcd";
//在定义时系统提示字符太长编译不通过。"abcd"长度为5
char str[10];
char*str1="0123456789";
strcpy(str,str1);
字符串长度为10,还有一个结束符’\0’,所以共11个字符,str1数组大小为10,这里越界了。
虽然越界了,但是并不报错,编译运行都可正常通过。(字符数组不要求最后一个字符为’\0’,是否需要加入’\0’,完全由系统决定,但是如果继续增加字符内容则会程序运行崩溃)
4.2 strcpy(str加粗样式2,str1)拷贝时,是根据str2中的’\0’判断结束的
4.3 内存布局相关问题
#include <stdio.h>
#include <string.h>
int main()
{
char s[] = "123456789";
char d[] = "123";
strcpy(d, s);
printf("%s,%s\n",d, s);
return 0;
}
输出
123456789,56789
5. 动态库相关
6. 字符串的常用操作
7. ANSI C标准宏
__LINE__ //在源代码中插入当前源代码行号
__FILE__ //在源文件中插入当前源文件名
__DATE__ //在源文件中插入当前的编译日期
__TIME__ //在源文件中插入当前编译时间
__STDC__ //当要求程序严格遵循ANSI C标准时该标识被赋值为1
__cplusplus //当编写C++程序时该标识符被定义
_WIN32//在程序运行在windows系统上被定义位1
linux //在程序运行在linux系统上被定义位1
__x86_64__ //在程序运行在64位系统上被定义位1
__i386__ //在程序运行在32位系统上被定义位1
8. 全局变量
- 内联函数、类可以在多个文件中同时定义,但同一个文件中只能定义一次;
- 全局变量、全局函数只能定义一次,在源文件中给出声明(或者引用含有声明的头文件)编译器会在链接时自动寻找其定义