24 / 07 / 10

「一生一芯」Learn C the hard way - Ex 9

练习 9:数组和字符串

#include <stdio.h> int main(int argc, char *argv[]) { int numbers[4] = {0}; char name[4] = {'a'}; // first, print them out raw printf("numbers: %d %d %d %d\n", numbers[0], numbers[1], numbers[2], numbers[3]); printf("name each: %c %c %c %c\n", name[0], name[1], name[2], name[3]); printf("name: %s\n", name); // setup the numbers numbers[0] = 1; numbers[1] = 2; numbers[2] = 3; numbers[3] = 4; // setup the name name[0] = 'Z'; name[1] = 'e'; name[2] = 'd'; name[3] = '\0'; // then print them out initialized printf("numbers: %d %d %d %d\n", numbers[0], numbers[1], numbers[2], numbers[3]); printf("name each: %c %c %c %c\n", name[0], name[1], name[2], name[3]); // print the name like a string printf("name: %s\n", name); // another way to use name char *another = "Zed"; printf("another: %s\n", another); printf("another each: %c %c %c %c\n", another[0], another[1], another[2], another[3]); return 0; }

附加题 1

将一些字符赋给numbers的元素,之后用printf一次打印一个字符,你会得到什么编译器警告?

#include <stdio.h> int main(int argc, char *argv[]){ int n[4] = {0}; printf("%d\n", n[0]); printf("%c\n", n[0]); n[0] = "a"; printf("%d\n", n[0]); printf("%c\n", n[0]); return 0; }
make ex9_1 cc -Wall -g -c ex9_1.c -o ex9_1.o ex9_1.c: In function ‘main’: ex9_1.c:10:14: warning: assignment to ‘int’ from ‘char *’ makes integer from pointer without a cast [-Wint-conversion] 10 | n[0] = "a"; | ^ cc -o ex9_1 ex9_1.o ⮞ ./ex9_1 0 444567564

附加题 2

names执行上述的相反操作,把names当成int数组,并一次打印一个intValgrind会提示什么?

⮞ valgrind ./ex9_2 ==201320== Memcheck, a memory error detector ==201320== Copyright (C) 2002-2024, and GNU GPL'd, by Julian Seward e t al. ==201320== Using Valgrind-3.23.0 and LibVEX; rerun with -h for copyri ght info ==201320== Command: ./ex9_2 ==201320== 97 a 5 ==201320== ==201320== HEAP SUMMARY: ==201320== in use at exit: 0 bytes in 0 blocks ==201320== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated ==201320== ==201320== All heap blocks were freed -- no leaks are possible ==201320== ==201320== For lists of detected and suppressed errors, rerun with: -s ==201320== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

无事发生……我不理解。

GPT:可能是因为 char 类型的元素虽然只有 1 字节,但在 printf 函数中,它们被自动提升为 int 类型。这种类型提升(integer promotion)在 C 标准中是合法的,并不会导致未定义行为。因此,Valgrind 并没有检测到内存访问错误。

附加题 3

有多少种其它的方式可以用来打印它?

  • 逐个字符打印

    • 使用 printf 打印各个元素

    • 使用 putchar 函数逐个打印字符

    • 使用指针遍历数组并打印

  • 作为字符串打印

    • 使用 printf%s 格式说明符

    • 使用 puts 函数

附加题 4

如果一个字符数组占四个字节,一个整数也占4个字节,你可以像整数一样使用整个name吗?你如何用黑魔法实现它?

  1. 使用联合体(union)

  2. 使用类型转换和指针

  3. 使用 memcpy 函数

附加题 5

拿出一张纸,将每个数组画成一排方框,之后在纸上画出代码中的操作,看看是否正确。

附加题 6

name转换成another的形式,看看代码是否能正常工作。

没看懂题目要求……将数组形式转化为指针吗?数组名即是地址。