C语言知识整理(三)


1指针

int x = 1, y = 2, z[10];

int *ip;   //ip是指向int类型的指针

ip = &x; //ip现在指向x

y = *ip;  //y的值现在为1

*ip = 0;  //x的值现在为0

ip = &z[0]; //ip现在指向z[0]


每个指针都必须指向某种特定的数据类型(一个例外情况是指向void类型的指针可以存放指向任何类型的指针,但它不能间接引用其自身。)


*ip = *ip + 10; 一元运算符*和&的优先级比算术运算符的优先级高。

*ip += 1 等同于 ++*ip 或 (*ip)++

其中(*ip)++的括号是必须的,否则将对ip进行加一,因为类似于*和++这样的一元运算符遵循从右往左的结合顺序。


若想直接修改主调函数中的变量的值可以用指针参数,例如

void swap(int *px, int *py)

{

}

swap(&a, &b);


2.指针与数组

通过数组下标所能完成的任何操作都可以通过指针来实现,而且速度更快。

int a[10];

int *pa;

pa = &a[0]; //指向a[0] 也可以写成pa = a;

pa+i 指向a[i],*(pa+i)引用的是数组元素a[i]的内容

a[i]可以写成*(a+i),在计算数组a[i]的值得时候,C语言实际先将转换成*(a+i)形式。

&a[i]和a+i的含义也是相同的。

但是,数组名和指针之间有一个不同之处是,指针是一个变量,pa=a和pa++都是合法的,数组名不是变量,因此类似a=pa和a++形式的语句是非法的。


把数组名传递给一个函数时,实际传递的是该数组第一个元素的地址,数组名参数必须是一个指针,也就是一个存储地址值的变量。


int strlen(char *s)

{

    int n;

    for(n = 0; *s != '\0'; s++)

        n++;

    return n;

}


strlen("hello world"); //字符串常量

strlen(array); //字符数组array

strlen(ptr); //ptr指向char类型的指针

上面的都可以正确执行。


在函数定义中,char s[]; 和 char *s 是等价的。


插一道,

char a1[] = {'k', 'o', 'b', 'e'};  //错误,出现乱码 strlen(a1) = 11;

char a1[] = {'k', 'o', 'b', 'e', '\0'}; //正确 strlen(a1) = 4;

char a2[4] = "kobe"; //错误 数组界限溢出

char a2[5] = "kobe"; //正确 strlen(a2) = 4


在字符串的内部表示中,字符数组以字符'\0'结尾。字符串常量占据的存储单元数也比引号内的字符数大1。


3.地址算术运算

C语言保证,0永远不是有效的数据地址,因此,返回0可用来表示发生了异常事件。

指针与整数之间不能相互转换,但0是惟一的例外:常量0可以赋值给指针,指针也可以和常量0进行比较。

如果指针p和q指向同一个数组的成员,那么他们之间就可以进行==、!=、<、>=的关系比较运算。(指针的算术运算中可使用数组最后一个元素的下一个元素的地址)、

指针可以与整数相加减

int strlen(char *s)

{

    char *p = s;

    while(*p != '\0')

        p++;

    return p-s;

}


4.

strcmp函数,根据s按照字典顺序小于、等于或大于t的结果分别返回负整数、0或正。

//数组实现

int strcmp(char *s, char *t)

{

    int i;

    for(int i = 0; s[i] == t[i]; i++)

        if(s[i] == '\0')

           return 0;

     return s[i] - t[i];

}


//指针实现

int strcmp(char *s, char *t)

{

    for( ; *s == *t; s++, t++)

        if(*s!='\0')

          return 0;


    return *s-*t;

}


5.指针数组的声明:char *lineptr[MAXLINES];具体使用可尝试写readlines函数。


6.在C语言中,二维数组实际上是一种特殊的一维数组,它的每个元素也是一个一维数组。数组元素按行存储,因此当按存储顺序访问数组时,最右边的数组下标变化得最快。

函数的参数声明中必须指明数组的列数,与行数没有太大关系:

f(int daytab[2][3]){} 也可以写成f(int daytab[][13]) {} 还可以写成f(int (*daytab)[13])

因为[]优先级高于*,所以必须使用圆括号。


除数组的第一维下标可以不指定大小外,其余各维都必须明确指定大小。


7.指针与多维数组

int a[10][20];

int *b[10];

区别,二维数组a分配了200个int类型长度的存储空间,对b来说仅仅分配了10个指针,并且没有对它们初始化,若b每个元素指向20个元素数组,那么分配200个int长度存储空间以及10个指针存储空间。指针数组一个优点在于数组的每一行长度可以不同,也就是说b的每个元素不必都指向20个元素的向量,某些可以2个,某些可以1个,某些也可以不指向任何向量。


8.命令行参数

调用主函数main时,它带有两个参数,argc用于参数计数,表示运行程序时命令行中参数的数目;第二个参数argv用于参数向量,是一个指向字符串数组的指针,其中每个字符对应一个参数。

按C语言的约定,argv[0]的值是启动该程序的程序名,因此argc的值至少为1。如果argc的值为1,说明程序名后面没有命令行参数。最后一个参数是argv[argc-1],另外ANSI标准要求argv[argc]的值必须为一个空指针。


9.类型定义 typedef

tyepdef int Length; Length len,a,b,c;

typedef struct tnode

{

    char *word;

    int count;

} Treenode;


typedef声明并没有创建一个新类型,只是为某个已存在的类型增加了一个名称而已。


10.联合是可以在不同时刻保存不同类型和长度的对象的变量,编译器负责跟踪对象的长度和对齐要求。联合提供了一种方式,以在单块存储区中管理不同类型的数据,而不需要再程序中嵌入任何同机器有关的信息。

union u_tag{

int ival;

float fval;

char *sval;

}u;

变量u必须足够大,以保存这3种类型中最大的一种,具体长度同具体的实现有关。







过早退出是一切失败的根源------高德纳




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断路器保护灵敏度校验整改及剩余电流监测试点应用站用交流系统断

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值