字符数组、指针,const

一、字符数组?
1、什么是字符数组?
在一个数组中,每个成员都是字符。
例如: char A[3];  -> 每一个成员都是字符来的,所以组成一个字符串。

2、字符数组的赋值?
char A[10] = {'h','e','l','l','o'};  剩余5个没有赋值的成员都是十进制0。  -> 等价于5个'\0'
char A[10] = {"hello"};              将字符串"hello"直接赋值给数组。
char A[10] = "hello";                与第2种写法一样的,{}可以省略。

思考题:
1)请问"char A[10] = {"10086"}与int A[10] = {1,0,0,8,6}"有什么区别?

char A[10] = {"10086"}  -> 其实10086这几个数字是一些字符来的,等价于 char A[10] = {'1','0','0','8','6'}
                                   char A[10] = {49,48,48,56,54};

int A[10] = {1,0,0,8,6}  -> 其实10086这几个数字是十进制数组来的。 等价于 int A[10] = {SOH,'\0','\0','\b',ACK};

2)请问能不能这样写?
int A[10] = "10086";    -> 不可以将一个字符串直接赋值给一个整型数组。
                           (因为字符串在内存中是一个地址来的,所以不能将一个地址赋值给一个整型数组)

int A[10] = {'1','0','0','8','6'};   -> 正确,等价于 int A[10] = {49,48,48,56,54};

3、从内存角度分析以下的问题。
char A[10] = {'h','e','l','l','o'};

char A[10] = {"hello"};

前者是从常量区将hello这5个字符拷贝到栈区数组中,然后系统就会补5个数字0,等价于字符'\0'。
后者是从常量区中将hello这个字符串拷贝到栈区数组中,然后字符串默认带一个'\0'在后面的,所以一共拷贝了6个字符到数组中,然后系统就会补4个数字0,等价于'\0'。

二、字符指针。
1、什么是字符指针?
指向一个字符变量的地址就是字符指针。

例子:
int a;
int *pa = &a;  -> pa就是一个整型指针,这个指针指向整型变量a的。

char b;
char *pb = &b; -> pb就是一个字符指针,这个指针指向字符变量b的。

2、有时候,我们会看到一个字符串赋值给一个字符指针?
char *p = "helloworld";   -> 正确
问题: 究竟字符指针是指向一个字符,还是一个字符串?
字符指针永远都是指向一个字符的,不可能指向一个字符串的,在这个例子中,指针p其实是存放在"helloworld"字符串第一个元素'h'的地址。

3、关于字符数组与字符指针需要注意的问题。
1)每一个字符串都是属于常量区的数据,而且字符串在常量区中往往是以'\0'作为结束标志。
   拷贝常量区的字符串时,是连'\0'一起拷贝。

2)常常会看到程序都是用这两种办法来保存字符串,那么它们有什么区别?
   char A[10] = "hello";
   char *p = "hello";

char A[10] = "hello";
在内存栈区中连续申请10个字节,然后使用变量A间接访问这片内存空间,将常量区中的"hello"这个字符串拷贝到变量A代表的这片内存空间。

char *p = "hello";
在内存栈区中连续申请8个字节,然后使用变量p间接访问这片内存空间,然后将常量区中的"hello"字符串中的第一个字符'h'的地址赋值给p对应的空间上。

3)%s   -> 输出一个字符串。
输出原则:
给定一个地址,判断该地址上的字符是不是'\0'
如果不是'\0',则打印该字符,并且将地址往后挪动一个单位,再继续判断。
如果是'\0',则结束打印。

  完成14/16/17题。

三、const关键词。
1、什么是const指针?
已经学习过非常多指针类型,例如:int* -> 整型指针  char* -> 字符指针。
const指针并不是指向const这种类型,const不是一种类型,是一个修饰关键词。

2、const使用场景。
const大多数都是用于修饰一个指针,很少会去修饰一个变量。
一般都是出现在函数的形式参数中。

3、举例子。

例子1: 
不使用const的情况:
#include <stdio.h>

int fun(int x) //x = age
{
    x = 100;  //x可以随意赋值
}

int main(int argc,char *argv[])
{
    int age = 18;
    fun(age);
    return 0;
}

使用const的情况:
#include <stdio.h>

int fun(const int x) //x可以赋值一次值,但是赋值了之后,就不能通过x去修改x的值。
{
    printf("x = %d\n",x);  -> 打印一下值是没有问题。
    x = 100;  //x可以随意赋值  -> 错误的
}

int main(int argc,char *argv[])
{
    int age = 18;
    fun(age);
    return 0;
}

例子2: 
#include <stdio.h>

int main(int argc,char *argv[])
{
    /*
    const int a = 100;
    //a存储了100,一旦赋值了100之后,那么就不能通过a修改a的值。
    printf("a = %d\n",a); //正确
    //a = 50; //编译报错
    */
    
    //const int a;  //随机值
    //a = 100;//编译报错
    //printf("a = %d\n",a);
    
    /*
    int a = 100;
    int b = 50;
    int *p = &a;
    p = &b;
    //请问*p得到什么?
    printf("*p = %d\n",*p); //50
    */
    
    /*
    int a = 100;
    int b = 50;
    int * const p = &a; //p储存着a的地址,一旦赋值了&a之后,那么就不能通过p修改p的值。
    p = &b; //error: assignment of read-only variable ‘p’
            //p就不能等于别的值。
            
    //请问*p得到什么? 
    //printf("*p = %d\n",*p);  //编译出错,没答案。
    */
    
    /*
    int a = 100;
    int b = 50;
    int * const p = &a; //p储存着a的地址,一旦赋值了&a之后,那么就不能通过p修改p的值。
                        //p就不能存储别的地址。
    *p = 30; //虽然p不能等于别的值,但是我们可以通过p修改p指向的东西。
    
    //请问*p得到什么? 
    printf("*p = %d\n",*p); //30
    */
    
    /*
    int a = 100;
    int b = 50;
    const int *p = &a; //p储存着a的地址,因为const不是修饰p,所以p可以等于别的值
    p = &b; //可以等于别的值。
    //请问*p得到什么? 
    printf("*p = %d\n",*p); //50
    */
    
    /*
    int a = 100;
    int b = 50;
    const int *p = &a; //p储存着a的地址,因为const不是修饰p,所以p可以等于别的值
                        //const是修改p指向的内容,所以不能通过p修改p指向的内容。
    *p = 30;
    //请问*p得到什么? 
    printf("*p = %d\n",*p); //编译出错
    */
    
    /*
    int a = 100;
    int b = 50;
    int const *p = &a;  //p储存着a的地址,因为const不是修饰p,所以p可以等于别的值
    p = &b;  //p可以等于别的值。
    //请问*p得到什么? 
    printf("*p = %d\n",*p);
    */
    
    /*
    int a = 100;
    int b = 50;
    int const *p = &a; //p储存着a的地址,因为const不是修饰p,所以p可以等于别的值
                    //const是修改p指向的内容,所以不能通过p修改p指向的内容。
    
    *p = 30;            
    //请问*p得到什么? 
    printf("*p = %d\n",*p); //编译出错
    */
    
    /*
    int a = 100;
    int b = 50;
    const int *p = &a; //不能通过p修改p指向的内容
    
    //*p = 30;
    a = 30; //但是我是通过a去修改的。
    //请问*p得到什么? 
    printf("*p = %d\n",*p); //30
    */
    
    /*
    const int a = 100;
    int *p = &a;
    *p = 30;
    //请问*p得到什么? 
    printf("*p = %d\n",*p);//30
    */
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值