`

C语法总结 数组和指针

 
阅读更多

 

数组

#define N 10
int a[N];
for(int i=0;i<N;i++) {
    a[i] = 0;
}

//初始化,没有被初始化到的数组下标就被设置为0
int a[10] = {1,2,3,4,5};
//等价于
int a[10] = {1,2,3,4,5,0,0,0,0,0};
//也可以写成入如下形式相当于把整个数组全部赋值为0
int a[10]={0};

//C99中可以指定对某个元素下标赋值,剩余的就被赋值为0
int a[15] = {[2]=11, [9]=33, [14]= 99};

//对数组使用sizeof运算符
int a[10];
sizeof(a);    //结果就是40
//sizeof 返回的是无符号的整形size_t,无符号和有符号之间运算会有危险,
//最好使用强制转型

//数组清零
#define SIZE   ( (int)(sizeof(a)/sizeof(a[0])) )

//多维数组初始化
int m[5][9] = {{1,2,3,4,5,6},
                        {2,3,54,5,6},
                        {4,5,6,7,8},
                        {3,5,6,7,11}};
//也可以省略外面的一层大括号
int m[5][9]  : {1,2,3,4,5,6,
                        {2,3,54,5,6,
                        {4,5,6,7,8,
                        {3,5,6,7,11};

//常量数组
const char hex_chars[] = {'0','1','2','3'};

//C99中也可以对多维数字进行指定下标的初始化
//C99还支持变长数组

 

 

 

指针

//定义一个指针
int *p;
//每个指针变量只能指向一种特定的类型
int *p;
double *d;
char *r;

//赋值和访问  &运算符是获取一个变量的地址值,  *那个运算符是间接寻址
int i, *p;
i = 10;
p = &i;
printf("%d",*p);

//这样的赋值是错误的
int i, *p;
i = 10;
*p = &i;    //这里是将 i的地址赋予p指向的内容,所以是错误的
                //*p是指针指向的内容,是一个具体的值,p才表示一个地址,所以
                //应该是 p = &i;  将i的地址赋予指针p才是正确的

//指针作为返回值
int *max(int *a, int *b) {
    if(*a > *b) {
        return a;
    }
    return b;
}
//注意,永远不要返回指向局部变量的指针
int *f(void) {
    int i;
    return &i;
}
//一旦函数f返回,变量i就不存在了,所以变量i的指针将是无效的,有的编译器会
//在这种情况下给出类似"function returns address of local variable"的
//警告



//未初始化的指针变量指向的是一个不确定的内存地址值
//用const保护参数,也就是指针指向的内容是常量不可改变,但指针内容本身是
//可以被改变的,也可以包含指针本身,还可以包含指针本身和指针指向的内容
//第一种情况,保护指针指向的内容,此时指针本身可以改变
int number = 100;
const int *p;
//*p = 0;
p = &number;
       
//第二种情况,保护指针本身,指针指向的内容可以被改变
int *const p2;
*p2 = 0;
//p2 = &number;
       
//第三种情况,包含指针本身,以及指针指向的内容
const int *const p3;
//*p3 = 0;
//p3 = &number;

  

 

 

 

指针和数组

//定义指针,指针p指向a数组的第一个元素
int a[10],  *p;
p = &a[0]

//设置数组a有10个元素
p = &a[2];           //指向数组a的第三个元素
int *q = p+3;      //指向数组a的第六个元素,也就是a[5]
p -= 4;                //指向数组a的第二个元素,也就是a[1]

//两个指针之间可以相减,但是两个指针必须都指向同一个数组,因为比较的是内存
//地址,如果两个数组指向的是两个不同的数组,最后计算出来的结果可能是未知的
//内存

 *运算符和 ++运算符(++运算符优先级高于*)

表达式 含义
*p++或者*(p++) 先自增p的值,然后再获得*p
(*p)++ 自增前的表达式是*P,以后再自增*p
*++p或*(++p) 先自增p,自增表达式的值是*p
++*p或++(*p) 先自增*p,那个自增后表达式的值是*p

 

//用数组名做指针
int a[10];
*a = 7;   //等于a[0] = 7;
//也可以通过指针来修改a[1]
*(a+1) = 12;    //等于a[1] = 12;
//遍历
for(p=&a[0]; p<a[N]; p++) {
    sum += *p;
}

//处理多维数组
int a[NUM_ROWS][NUM_COLS];
int *p;
for(p=&a[0][0]; p<= &a[NUM_ROWS-1][NUM_COLS-1]; p++) {
    *p = 0;
}

//C99中的指针和变成数组

 

 

 

指针的高级应用

//内存分配函数,这些都是声明在<stdlib.h>头文件中
//malloc()函数      分配内存块,但是不对内存块进行初始化
//calloc()函数       分配内存块,并且对内存块进行初始化
//realloc()函数     调整先前分配的内存块大小
//空指针用表示   不指向任何地方的指针,用名为 NULL  的宏来表示
//NULL 定义在<stdlib.h>中
p = malloc(1000);
if(NULL == p) {
     //分配失败
}

//malloc函数原型,它返回的是void*类型指针,所以需要转型,这个void*就代表
//任何类型
void *malloc(size_t size);
//分配字符串时需要分配n+1大小空间,因为字符串最后是\0结尾
p =(char*) malloc(n+1);
//分配数组空间,注意分配时必须使用sizeof计算单个值占多少字节
int *a;
a = malloc(n * sizeof(int));

//calloc函数原型,为nmemb个元素的数组分配内存空间,其中每个元素长度
//都是size个字节,如果要求的空间无效会返回空指针
void *calloc(size_t nmemb, size_t size);
a = calloc(n, sizeof(int));

//realloc函数原型,其中ptr必须指向先前通过malloc,calloc,realloc的调用
//获得的内存块,size表示新尺寸可能会大于或小于原有尺寸。
void *realloc(void *ptr, size_t size);

 C标准列出了几条关于realloc函数的规则

1.当扩展内存块时,realloc函数不会对添加进内存块的字节数进行初始化

2.如果realloc函数不能按要求扩大内存块,那么它会返回空指针,并且在原油的内存块中的数据不会发生改变

3.如果realloc函数调用时以空指针作为第一个实际参数,那么它的行为就像malloc函数一样

4.如果realloc函数被调用时以0作为第二个实际参数,那么它会释放掉内存。

注意:一旦realloc函数返回一定要对所有指针进行更新,因为ralloc函数可能会使内存块移动到了其他地方

//用free函数释放动态申请的内存,其原型为
void free(void *prt);
//悬空指针问题
char *p = malloc(4);
free(p);
strcpy(p, "abc");      //此时p指向的内存已经被释放掉了,再对其修改可能会造成
//严重的错误

//结构体
struct node {
    int value;
    struct node *next;
};
struct node *new_node= NULL;
new_node = malloc(sizeof(struct node));
//写成这样是不对的,我们需要申请结构体大小的空间,而这样申请的是指针大小的
//空间,一个指针可能是4个字节,这样实际上就申请了4个字节
new_node = malloc(sizeof(new_node));

//  ->运算符
(*new_node).value = 10;
//等价于
node_new->value = 10;

//指向指针的指针
char **ptr;
*ptr = "abc";    //ptr是指向"abc"的地址


//指向函数的指针
//假设函数integrate的原型如下: (*f)说明f 是个指向函数的指针
double integrate(double (*f)(double), double a, double b);
//也可以写成:
double integrate(double f(double), double a, double b);
//调用integrate时,将把一个函数名作为第一个实际参数,注意sin后面没有括号
//C编译器会产生指向函数的指针而不是产生函数调用的代码
result = integrate(sin, 0.0, PI/2);
//在函数integrate中, *f 表示调用f 所指向的函数,*f 就是调用sin函数
// (*f)(x) 和f(x)都是一样的,但是用(*f)(x)更好,说明是f是指向函数的指针


//C函数库中的qsort函数原型
void qsort(void *base, size_t nmemb, size_t size,
        int (*compar)(const void*, const void*));
//base是指向数组中的第一个元素,nmemb是要排序元素的数量,size是每个
//数组元素的大小,compar是指向比较函数的指针

int compare_parts(const void *p, const void *q) {
    const struct part *p1 = p;
    const struct part *p2 = q;
    if(p1->number < p2->number) {
        return -1;
    }
    else if(p1->number == p2->number) {
        return 0;
    }
    return 1;
}
//还可以写成:
int compare_parts(const void *p, const void *q) {
    return ((struct part*)p)->number - ((struct part*)q)->number;
}

//指向函数的指针,可以指向任何参数是int,返回void类型的函数
void (*pf) (int);
void fun(int x);
pf = fun;       //让pf指向函数fun,注意fun前面不需要加 &
pf(100);


//受限指针
int * restrict p;
//灵活数组成员
struct vstring{
    int len;
    char chars[N];
};
//这里N表示一个字符串最大长度的宏,但是分配最大长度会导致浪费,于是采用
//如下方式申明chars长度
struct vstring{
    int len;
    char chars[1];
};
struct vstring * str = malloc(sizeof(struct vstring) +n-1);
//这样就看以达到目的了,并且内存不会浪费,这样叫 struct hack 技术
//C99支持灵活数组成员,当结构体最后一个是数组时可以省略长度
struct vstring{
    int len;
    char chars[];
};


 

定义NULL为

#define NULL (void*)0;

 如果把NULL 定义为0,那么把NULL赋给整型变量index是合法的,但是把NULL定义为(void*)0 则表示把指针赋值给了整型变量

 

将malloc函数的值类型强制转换没有任何好处,这是来自于经典C的习惯。

 

 

 

 

 

参考:

理解一般指针和指向指针的指针

 

 

分享到:
评论

相关推荐

    c语言中 数组名和指针的区别

    在C语言中,数组名和指针之间存在微妙且重要的区别,这往往让初学者感到困惑。虽然在某些上下文中,它们看似可以互换使用,但深入理解它们的本质差异对于编写高效、安全的代码至关重要。 ### 一、数组名与指针的...

    数组和指针之间的区别与联系

    在C语言中,数组和指针是两个非常重要的概念,它们之间既有明显的区别,也有紧密的联系。数组是一种数据结构,而指针则是一种特殊的数据类型,用于存储内存地址。理解这两者的差异和关联对于深入学习C语言至关重要。...

    C语言数组、指针与编程技巧

    ### C语言数组、指针与编程技巧 #### 一、数组的基本概念与使用方法 **数组**是一种数据结构,用于...以上是对C语言中数组、指针以及一些编程技巧的详细介绍,希望能够帮助读者更好地理解和掌握这些重要的编程概念。

    数组和指针使用及区别详解

    在编程中,数组和指针是两种非常基础且重要的概念,它们在处理数据时起着核心作用。数组是一组相同类型的元素的集合,通过索引来访问每个元素。指针则是一个变量,它存储的是内存地址,这个地址通常指向一个变量或...

    C语言程序设计第4章数组和指针

    在C语言中,数组和指针是编程时非常重要的概念,尤其在处理大量数据或实现高效算法时。在第四章“数组和指针”中,我们主要探讨了以下几个知识点: 1. **数组的概念**: 数组是一组相同类型的变量,它们按照下标...

    (完整word版)c语言(函数-数组-指针)练习题.doc

    "C语言函数、数组、指针练习题" 1. 选择题1:C程序的执行是从main函数开始执行的。因此,正确答案是A。 2. 选择题2:使指针p1指向变量a,...通过这些练习题,我们可以熟悉C语言的语法和使用方法,从而提高编程能力。

    C语言程序设计数组指针与字符串PPT课件.pptx

    【C语言程序设计:数组、指针与字符串】 在C语言中,数组是编程...综上所述,C语言的数组和指针是编程的基础,它们提供了高效地处理和操纵内存中数据的能力。理解和熟练运用这些概念对于编写高效的C语言程序至关重要。

    C语言培训 指针 数组 结构体 链表

    掌握C语言的关键在于理解和运用指针、数组、结构体和链表等核心概念。 **一、学习编程语言的一些建议** 1. **多动手**:编程实践是学习编程的最有效方式。通过编写和调试程序,可以深入理解语言的特性和工作原理。...

    C程序用数组的指针控制LED流水灯,源代码.rar

    本项目利用C语言编程,通过数组的指针来实现对LED流水灯的控制,这涉及到C语言的基础语法、指针操作以及系统相关编程。 首先,我们要理解C语言中的指针。指针是C语言的一个重要特性,它存储的是内存地址,可以用来...

    C语言课程 数组 指针 结构体

    本课程聚焦于C语言中的核心概念,包括数组、指针和结构体,这些都是理解和编写C程序的关键。 首先,让我们深入探讨数组。数组是C语言中存储多个相同类型数据的一种方式。你可以将其想象为一个连续的内存空间,每个...

    C语言中数组的运算

    本资料包包含46个C语言源文件,专门探讨数组的运算,特别是各种排序算法的实现,这对于理解和掌握C语言的数组操作至关重要。下面我们将详细讲解数组在C语言中的概念、操作以及常见的数组运算实例。 1. **数组定义与...

    C/C++中数组与指针的关系

    - **数组指针** (`int (*pa)[4][3];`):可以用来访问整个数组。 - **行指针** (`int (*pr)[3];`):可以用来访问数组中的某一行。 - **列指针** (`int *p;`):可以用来访问数组中的某个元素。 对于二维数组`int a[4]...

    数组指针,函数指针应用

    本主题将深入探讨数组指针和函数指针的应用,通过提供的源代码实例,我们可以更好地理解这两种概念的实用性和灵活性。 首先,数组在C/C++中本质上是一段连续的内存空间,存储相同类型的数据。数组名通常被视为指向...

    数组与指针

    在C语言中,定义一维数组的语法是通过指定元素类型、数组名和元素个数来实现。例如,int a[10]定义了一个名为a的整型数组,它包含10个整数。 数组的引用需要在定义之后进行,并且只能逐个引用数组元素,不能一次...

    c语言编程100例算法指针,数组

    C语言编程100例算法指针数组 本资源是一个C语言编程的集合,共有五个程序,每个程序都解决了一个...这五个程序展示了C语言编程的多样性和灵活性,並展示了数组、指针、循环语句和条件语句等基本语法和数据结构的应用。

    C高级语言程序设计:07数组与指针.pptx

    数组和指针是C语言中非常重要的概念。数组提供了存储一系列相同类型数据的有效方式,而指针则提供了灵活地访问和操作内存的能力。理解这两个概念对于掌握C语言至关重要,并且对于编写高效、安全的程序非常重要。通过...

    深入理解数组指针与指针数组的区别

    总结来说,数组指针`int (*p)[n]`是一个指向数组的指针,而指针数组`int *p[n]`是一个包含`n`个指针的数组。两者在声明、赋值和使用方式上都有所不同。理解这些区别对于编写高效、无误的C/C++代码至关重要。在实际...

    c语言习题 (数组).zip

    C语言是一种基础且强大的编程语言,它以其简洁的语法和高效执行著称。在C语言中,数组是一种非常重要的数据结构,它允许我们存储多个相同类型的数据在一个单一的变量中。这个“c语言习题(数组).zip”文件很可能...

    c语言之语法代码集,文件操作 数组 指针 结构体 共同体

    本资源包“c语言之语法代码集”聚焦于C语言的核心语法元素,包括文件操作、数组、指针、结构体和共同体,这些都是C语言编程的基础和核心。 1. **文件操作**:在C语言中,文件操作是通过标准库函数如`fopen`, `...

Global site tag (gtag.js) - Google Analytics