12. sizeof和strlen在使用中的注意点

在使用 sizeofstrlen 时,有一些关键的注意点,特别是在不同的场景下,这些操作符和函数的行为可能会有所不同。以下是一些常见的注意事项:

1. sizeof 的注意事项

1.1 适用于编译时
  • sizeof 是在编译时确定的,它不会在运行时计算数据大小。因此,对于数组、结构体等静态分配的类型,sizeof 返回的是类型的实际大小。
1.2 指针与数组的区别
  • 对于数组和指针,sizeof 的行为不同:

    • 对于数组,sizeof 返回整个数组的字节大小。
    • 对于指针,sizeof 返回的是指针本身的大小,而不是指向的数据的大小。

    示例:

    char arr[10];
    char *ptr = arr;
    
    printf("Size of array: %lu\n", sizeof(arr));  // 返回 10
    printf("Size of pointer: %lu\n", sizeof(ptr));  // 返回指针的大小(在64位系统上通常为 8)
    

    注意:在函数参数中,传递数组会退化为指针,因此 sizeof 无法在函数参数中用于数组大小。

1.3 结构体与填充字节
  • 对于结构体,sizeof 计算结构体的总大小,包括填充字节(padding)。因此,如果结构体成员的类型对齐要求不同,sizeof 可能会比所有成员大小的总和要大。

    示例:

    struct Example {
        char c;    // 1 字节
        int i;     // 4 字节
    };
    
    printf("Size of struct: %lu\n", sizeof(struct Example));  // 8 字节(由于内存对齐)
    
1.4 数组退化为指针时的行为
  • 当数组传递给函数时,数组会退化为指针,在函数内使用 sizeof 时,结果返回的是指针的大小,而不是数组的大小。

    示例:

    void func(char arr[]) {
        printf("Size inside function: %lu\n", sizeof(arr));  // 返回的是指针大小,8 字节(64 位系统)
    }
    
    int main() {
        char arr[10];
        printf("Size in main: %lu\n", sizeof(arr));  // 返回数组的大小,10
        func(arr);  // 调用函数
        return 0;
    }
    
1.5 动态分配的内存
  • 对于使用 malloc 等动态分配的内存,sizeof 返回的是指针的大小,而不是分配内存块的大小。

    示例:

    int *ptr = (int *)malloc(10 * sizeof(int));
    printf("Size of pointer: %lu\n", sizeof(ptr));  // 返回指针大小,而不是分配的内存大小
    

2. strlen 的注意事项

2.1 必须是以 '\0' 结尾的字符串
  • strlen 只能用于以 '\0' 结尾的 C 字符串。如果字符串未以 '\0' 结尾,strlen 的行为是未定义的,可能会导致崩溃或错误计算。

    示例:

    char str[5] = {'H', 'e', 'l', 'l', 'o'};  // 没有 '\0'
    printf("String length: %lu\n", strlen(str));  // 未定义行为,可能崩溃
    
2.2 计算的是字符数,不包含 '\0'
  • strlen 返回的长度不包括终止符 '\0',而 sizeof 计算的数组大小是包含 '\0' 的。

    示例:

    char str[] = "Hello";
    printf("Size of string: %lu\n", sizeof(str));  // 返回 6,包括 '\0'
    printf("Length of string: %lu\n", strlen(str));  // 返回 5,不包括 '\0'
    
2.3 不能用于未初始化的指针
  • strlen 不能用于指向未初始化的指针或非字符串内容的指针。如果指针未指向有效的字符串,调用 strlen 会导致未定义行为。

    示例:

    char *ptr;
    // ptr 未初始化,调用 strlen 会导致崩溃或未定义行为
    // printf("Length: %lu\n", strlen(ptr));  
    
2.4 指针与数组的不同
  • strlen 在处理指针和数组时,结果是基于指向的字符串的实际内容,而不是内存大小。

    示例:

    char str[] = "Hello";
    char *ptr = "World";
    
    printf("Length of str: %lu\n", strlen(str));  // 返回 5
    printf("Length of ptr: %lu\n", strlen(ptr));  // 返回 5
    
2.5 动态分配的字符串
  • 对于动态分配的字符串,strlen 返回的是指向的字符串长度,而不是分配内存的大小。

    示例:

    char *ptr = (char *)malloc(10 * sizeof(char));
    strcpy(ptr, "Hello");
    printf("Length of string: %lu\n", strlen(ptr));  // 返回 5
    

3. 常见问题汇总

  • sizeof 返回的是数据类型的 总大小,包括填充字节或空字符,而 strlen 返回字符串中实际字符的数量。
  • sizeof 计算的是 编译时确定的大小,而 strlen 在运行时计算字符串长度。
  • sizeof 适用于任何数据类型,而 strlen 只能用于以 '\0' 结尾的字符串。
  • 使用 strlen 时,确保字符串以 '\0' 结尾,否则会导致未定义行为。
  • 动态分配的内存,使用 sizeof 返回的是指针大小,而 strlen 计算的是字符串的长度。

4. 总结注意点

  • sizeof 在编译时确定内存大小,适用于任何类型,特别注意数组和指针的区别。
  • strlen 在运行时计算字符串长度,确保字符串是以 '\0' 结尾的 C 字符串,并小心未初始化指针。
  • 动态内存 分配和指针的使用时,需要注意 sizeof 返回的是指针大小,而不是分配内存块的大小。

你可能感兴趣的:(关于c语言的犄角旮旯,c,road,linux,c语言,linux)