学习笔记
- 字、字节、位三者的关系。计算机的内存由数以亿万计的位组成,每个位可以容纳值0或1。由于一个位所能表示的值的范围太有限,所以单独的位用处不大,通常许多位合成一组作为一个单位,这样就可以存储范围较大的值。在许多现代的机器上,每个字节包含8个位,可以存储无符号值0至255,或者有符号值-128至127。为了存储更大的值,把两个或更多的字节合成一起作为一个更大的内存单位。许多机器以字为单位存储整数,每个字一般由2个或4个字节组成
- 标准定义了
NULL
指针,它作为一个特殊的指针变量,表示不指向任何东西。对指针进行解引用操作可以获得它所指向的值。但从定义上看,NULL
指针并未指向任何东西。因此,对一个NULL
指针进行解引用操作是非法的。对NULL
指针执行间接访问操作的后果因编译器而异,两个常见的后果分别是返回内存位置零的值以及终止程序 - 定义指向字符串常量的指针作为函数参数,在函数中不能对字符串进行修改。因为常量字符串是不可变的,尝试修改它们的行为是未定义的,可能导致程序崩溃或产生不确定的行为。解决办法是定义字符数组来存放字符串常量
书后练习
问题1
如果一个值的类型无法简单地通过观察它的位模式来判断,那么机器是如何知道应该怎样对这个值进行操纵的
无论是程序员还是计算机都无法通过值的位模式来判断它的类型
类型是通过值的使用方法隐式地确定的
编译器能够保证值的声明和值的使用之间的关系是适当的,从而帮助我们确定值的类型
问题4
在有些机器上,编译器在内存位置零存储0这个值。对NULL指针进行解引用操作将访问这个位置。这种方法会产生什么后果
两个常见的后果分别是返回内存位置零的值以及终止程序
问题6
下面的代码段有没有问题?如果有的话,问题在哪里
int array[ARRZY_SIZE];
int *pi;
for( pi = &array[0]; pi < &array[ARRAY_SIZE]; )
*++pi = 0;
代码段想实现的功能是将数组元素全部初始化为0
问题1:无法将数组的最后一个元素初始化为0
解决办法:pi <= &array[ARRAY_SIZE];或者pi < &array[ARRAY_SIZE + 1];
问题2:访问数组下标越界
解决办法:*pi++ = 0;
编程练习3
编写函数reverse_string,它的原型如下
void reverse_string( char * string );
函数把参数字符串中的字符反向排列。请使用指针而不是数组下标,不要使用任何C函数库中用于操纵字符串的函数。提示:不需要声明一个局部数组来临时存储参数字符串。
#include <stdio.h>
#include <stdlib.h>
/* 将参数字符串中的字符反向排列 */
void reverse_string( char *string ){
char *ptr = string;
/* 将ptr指向字符串末尾 */
while( *ptr != '\0' )
ptr++;
/* 将ptr指向字符串的最后一个字符 */
ptr--;
/* 如果两个指针没有相遇则继续循环 */
while( string < ptr ){
/* 交换两个指针指向的字符 */
char temp = *string;
*string++ = *ptr;
*ptr-- = temp;
}
}
int main( int argc, char *argv[] ){
char test[] = "abcdefg";
printf("Original string is : %s\n", test);
reverse_string( test );
printf( "Changed order string is : %s\n", test );
return EXIT_SUCCESS;
}
在写这个程序时遇到了一个问题,在 main
函数中定义字符串时我写的语句是 char *test = "abcdefg";
,程序一直报错。这是因为我将 test
指针初始化为一个常量字符串的地址。而在C语言中,常量字符串是不可变的,尝试修改它们的行为是未定义的,可能导致程序崩溃或产生不确定的行为。为了修复这个问题,可以将 test
定义为一个字符数组,char test[] = "abcdefg";
,并将字符串内容赋值到数组中,而不是直接赋值给指针,这样就能安全地修改字符串中的内容。