每日一c,对指针,数组,字符串常量之间的梳理(一)

来源:互联网 发布:萍乡教育网网络管理 编辑:程序博客网 时间:2024/06/05 07:51

时间:2017.5.31    21:24

万丈高楼平地而起,学好IT,得把纯c基础打牢实了。最近,乘着还有空闲时间,从新梳理哈自己的纯C关系树。一边学习一边记录,蛮不错的大笑

指针与数组的相同与不同
一.作为函数参数时,在语句或者表达式中使用数组时,我们可以采用数组或者指针的任何一种形式,除此之外的其他情况,指针与数组不能互唤.
规则总结:
1.表达式中的数组名被编译器当作一个指向该数组的第一个元素的指针
2.下标总是和指针的偏移量相同
3.在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针
例:
#include <stdio.h>
int main()
{
     //注意sizeof(num)的长度应该为10*4=40 
int num[] = {0,1,2,3,4,5,6,7,8,9};
printf(" sizeof(num) = %d\n", sizeof(num) );

//注意sizeof(str)的长度应该为11,包括字符串后面的'\0' 
char str[] = "0123456789";// 
printf(" sizeof(str) = %d\n", sizeof(str) );

//注意sizeof(str1)的长度应该为10,不包括字符串后面的'\0',但是,最好将字符串的最后一个字符设定为空
char str1[] = {'0','1','2','3','4','5','6','7','8','9'};
printf(" sizeof(str1) = %d\n", sizeof(str1) );

//&num的类型为'int (*)[10]',表示的是一个指向长度为10的整形数组的指针
int (*ptoint)[10] = &num;
printf(" sizeof(ptoint) = %d, (*ptoint)[9] = %d\n", sizeof(ptoint), (*ptoint)[9] );

//&str的类型为'char (*)[11]',表示的是一个指向长度为11的字符数组的指针,注意str数组的长度是11,而不是10
char (*ptostr)[11] = &str;
printf(" sizeof(ptostr) = %d, (*ptostr)[9] = %c\n", sizeof(ptostr), (*ptostr)[9] );

//由于p指向的是数组num[5],所以对下标取负值后,不会超出数组的正常取值范围
//该例子也说明了为什么下标检查在c语言中是一项困难的任务:下标引用可以作用于任意的指针,而不仅仅是数组名
//作用于指针的下标引用的有效性即依赖于该指针当时恰好指向什么内容,也依赖于下标的值
int *p = num + 5;
printf(" p[-1] = %d, p[0] = %d, p[1] = %d \n", p[-1],p[0],p[1] );

//下面的表达式中,'num[5]和5[num]'的值是一样的,把它们转换成对等的间接访问表达式,它们都等同于*(num + 2)
//'5[num]'这个古怪的表达式之所以可行,缘于C实现下标的方法。对编译器来说,这两种形式并无差别
//但是,决不应该编写形如'5[num]'的表达式,因为它会大大的影响程序的可读性
printf(" num[5] = %d, 5[num] = %d \n", num[5], 5[num] );
     getchar();
return 0;
}

字符串常量
.当一个字符串常量出现在表达式中时,它的值是指针常量。编译器把该字符串的一份拷贝存储在内存的某个位置,并存储一个指向第一个字符的指针。我们可以对字符串常量进行下标引用、间接访问以及指针运算.
1 “xyz”+2
字符串常量实际上是个指针,这个表达式计算“指针值加上1”的值。它的结果也是个指针,指向字符串中的第二个字符z
2 * “xyz”
对一个指针执行间接访问操作时,其结果就是指针所指向的内容。字符串常量的类型是“指向字符的指针”,所以这个间接访问的结果就是它所指向的字符:x。注意表达式的结果并不是整个字符串,而只是它的第一个字符。
3 “xyz[2]
同样可以推断出上面这个表达式的值就是字符z
例:
#include<stdio.h>
//接受一个无符号整型值,把它转换成字符,并打印出来
//如果是打印16进值的数,可以用这种方法:putchar( "0123456789ABCDEF"[ value % 16 ] )
void binary_to_ascii( unsigned long value )
{
    unsigned long quotient;


quotient = value / 10;
if( quotient != 0 )
binary_to_ascii( quotient );


putchar( "0123456789"[ value % 10 ] );

int main(void)
{
//字符串常量实际上是个指针,这个表达式计算"指针值加上1"的值。它的结果也是个指针,
   //指向字符串中的第二个字符:z
printf("%s\n","xyz"+2);
//对一个指针执行间接访问操作时,其结果就是指针所指向的内容。
    //字符串常量的类型是"指向字符的指针",所以这个间接访问的结果就是它所指向的字符:x
    printf( "%c\n", *"abcdefg" );
   //同样可以推断出上面这个表达式的值就是字符d
    printf( "%c\n", "abcdefg"[3] );
 binary_to_ascii( 1234567 );
}

用字符串常量初始化指针和数组
.定义指针时,编译器并不会为指针所指的对象分配空间,它只是分配指针本身的空间,除非在定义的同时就赋给指针一个字符串常量进行初始化。
例:
char *p = breadfruit;
注意只有对字符串常量才是如此。不能指望为浮点数之类的变量分配空间,如:
float *pip = 3.14;     /*错误,无法通过编译*/
在ANSI c中,初始化指针时所创建的字符串常量常被定义为只读。如果试图通过指针修改这个字符串值,程序会出现未定义的行为。在有些编译器中,字符串常量被存放在只允许读取的文本段中,以防止它被修改。

数组也可以用字符串常量进行初始化:
char a[] =gooseberry;
与指针相反,由字符串常量初始化的数组是可以修改的。比如下面的语句:
strncpy( a,black, 5 );
将数组的值修改为blackberry”。
例:
#include <stdio.h>
#include <string.h>
 int main(void)
 {
    const char *p = "this is a example";
//char *pi = 3.14; //这样定义是错误的,无法通过编译
//p[0] = 'T'; //修改该字符串常量时,编译是没问题,但是运行时会出现异常

char a[] = "gooseberry";
    strncpy( a, "black", 5 );

printf("%s\n", p );
printf("%s\n", a );
return 0;
 
 }






阅读全文
0 0
原创粉丝点击