天天看点

C语言学习笔记一、变量、函数二、指针三、补充四、C语言实例

C语言学习笔记

  • 一、变量、函数
    • 1. typedef
    • 2. size_t
    • 3. enum(枚举)
  • 二、指针
    • 1. 指针基本概念:*&
    • 2. 函数指针与回调函数
      • 2.1 函数指针作为某个函数的参数
      • 2.2 回调函数·传值调用函数
      • 2.3 回调函数·引用调用函数
  • 三、补充
    • 1. 字符串
    • 2. 结构体
      • 指向结构的指针
    • 3. 共用体
    • 4. 位域
  • 四、C语言实例

一、变量、函数

1. typedef

使用typedef为现有类型创建别名,定义易于记忆的类型名

typedef int size;
void measure(size*psz);
           

typedef 还可以掩饰复合类型,如指针和数组。

例如,你不用像下面这样重复定义有 81 个字符元素的数组:

char line[81];
char text[81];
           

只需这样定义,Line类型即代表了具有81个元素的字符数组,使用方法如下:

typedef char Line[81];
Line text,line;
           

同样,可以像下面这样隐藏指针语法:

typedef char* pstr;
int mystrcmp(const pstr p1,const pstr p3);
           

const char*

char* const

表达的并非同一意思,

const char*

的意思是创建一个指向char类型的指针且不能更改指向地址上的值,而

char* const

则是不能更改指向的地址;

char* const p

: 定义一个指向字符的指针常数,即const指针,常量指针。

const char* p

:定义一个指向字符型常量的指针。

2. size_t

理解:无符号整型,作为大小的表示量。int可正可负,只作为整数。

size_t 的定义在 stddef.h、stdio.h、stdlib.h、string.h、time.h 和 wchar.h 这些标准 C 的头文件中,包含以上任一头文件,则表明 size_t 将作为一个全局关键字。

在 32 位架构中被普遍定义为:

在 64 位架构中被定义为:

从定义可以看出,size_t 是一种无符号的整型(unsigned int、unsigned long、unsigned long long),取值范围是目标平台下最大的可能范围。

3. enum(枚举)

枚举是 C 语言中的一种基本数据类型,它可以让数据更简洁,更易读。

枚举语法定义格式为:

菜鸟教程展开>>

二、指针

1. 指针基本概念:*&

笔记:一个指针指向一个数组,用 ptr = &var[0] 与 ptr = var一样,默认存储该数组首位地址。

#include <stdio.h>

const int MAX = 3;

int main()
{
    int  var[] = { 10, 100, 200 };
    int  i, * ptr,*pt;

    /* 指针中最后一个元素的地址 */
    ptr = &var[MAX - 1];
    pt = var;
    for (i = 0; i < 2 ; i++)
    {
        pt = pt++;
    }
    for (i = MAX; i > 0; i--)
    {

        printf("存储地址:var[%d] = %p\n", i - 1, ptr);

        printf("存储值:var[%d] = %d\n", i - 1, *ptr);
        printf("存储地址:var[%d] = %p\n", i - 1, pt);

        /* 指向下一个位置 */
        ptr--;
        pt--;
    }
    return 0;
}
           

2. 函数指针与回调函数

2.1 函数指针作为某个函数的参数

函数指针变量可以作为某个函数的参数来使用的,回调函数就是一个通过函数指针调用的函数。

简单讲:回调函数是由别人的函数执行时调用你实现的函数。

以下是来自知乎作者常溪玲的解说:

你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。

  • 实例

实例中

populate_array

函数定义了三个参数,其中第三个参数是函数的指针,通过该函数来设置数组的值。

实例中我们定义了回调函数

getNextRandomValue

,它返回一个随机值,它作为一个函数指针传递给

populate_array

函数。

populate_array 将调用 10 次回调函数,并将回调函数的返回值赋值给数组。

#include <stdlib.h>  
#include <stdio.h>
 
// 定义回调函数
void populate_array(int *array, size_t arraySize, int (*getNextValue)(void))
{
    for (size_t i=0; i<arraySize; i++)
        array[i] = getNextValue();
}
 
// 获取随机值
int getNextRandomValue(void)
{
    return rand();
}
 
int main(void)
{
    int myarray[10];
    /* getNextRandomValue 不能加括号,否则无法编译,因为加上括号之后相当于传入此参数时传入了 int , 而不是函数指针*/
    populate_array(myarray, 10, getNextRandomValue);
    for(int i = 0; i < 10; i++) {
        printf("%d ", myarray[i]);
    }
    printf("\n");
    return 0;
}
           

代码解释:

int *array

int array[]

效果相同,但是两者区别在于:

其实使用数组名

int a[]

定义也相当于指针

int *a

.比如,要访问

int a[5]

实际上是先获得这个数组的头指针

int*a

,然后在内存中偏移5个int的数据长度

int *(a+5)

,也就是从代码的理解上,可以认为

int a[5]

int *(a+5)

等价,

作者:林扬飞 链接:https://www.zhihu.com/question/23278865/answer/28430556

2.2 回调函数·传值调用函数

向函数传递参数的传值调用方法,把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数不会影响实际参数。

默认情况下,C 语言使用传值调用方法来传递参数。一般来说,这意味着函数内的代码不会改变用于调用函数的实际参数。

/* 函数定义 */
void swap(int x, int y)
{
   int temp;

   temp = x; /* 保存 x 的值 */
   x = y;    /* 把 y 赋值给 x */
   y = temp; /* 把 temp 赋值给 y */
  
   return;
}
           
菜鸟教程展开>>
补充:C语言return的用法详解

2.3 回调函数·引用调用函数

通过引用传递方式,形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作。

传递指针可以让多个函数访问指针所引用的对象,而不用把对象声明为全局可访问。

/* 函数定义 */
void swap(int *x, int *y)
{
   int temp;
   temp = *x;    /* 保存地址 x 的值 */
   *x = *y;      /* 把 y 赋值给 x */
   *y = temp;    /* 把 temp 赋值给 y */
  
   return;
}
           
菜鸟教程展开>>

三、补充

1. 字符串

C 中有大量操作字符串的函数:

序号 函数 目的
1 strcpy(s1,s2); 复制字符串 s2 到字符串 s1。
2 strcat(s1,s2); 连接字符串 s2 到字符串 s1 的末尾。
3 strlen(s1,s2); 返回字符串 s1 的长度。
4 strcmp(s1,s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回小于 0;如果 s1>s2 则返回大于 0。
5 strchr(s1,s2); 返回一个指针,指向字符串 s1 中字符 ch 的第一次出现的位置。
6 strstr(s1,s2); 返回一个指针,指向字符串 s1 中字符串 s2 的第一次出现的位置。

2. 结构体

struct tag { 
    member-list
    member-list 
    member-list  
    ...
} variable-list ;
           

tag

是结构体标签。

member-list

是标准的变量定义,比如 int i; 或者 float f,或者其他有效的变量定义。

variable-list

结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。下面是声明 Book 结构的方式:

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;
           

指向结构的指针

您可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似,如下所示:

现在,您可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:

为了使用指向该结构的指针访问结构的成员,您必须使用

->

运算符,如下所示:

笔记:

struct A *p;

struct A {};

区别

//定义A为:内含整数的结构体//
struct A {
    int data;     
};
 
int main()
{
    struct A *b; //定义b为指向 满足标签A的结构体 的指针//
    struct A c; //定义c为满足标签A的结构体//
     
    b = &c;  //指针b中存的是c的地址//
 
    c.data = 100; 
 
    printf("%d\n", b->data);    
 
    return 0;
}
           
菜鸟教程展开>>

3. 共用体

展开>>补充:共用体和结构体的区别

4. 位域

#include <stdio.h>
#include <string.h>
 
/* 定义简单的结构 */
struct
{
  unsigned int widthValidated;
  unsigned int heightValidated;
} status1;
 
/* 定义位域结构 */
struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status2;
 
int main( )
{
   printf( "Memory size occupied by status1 : %d\n", sizeof(status1));
   printf( "Memory size occupied by status2 : %d\n", sizeof(status2));
 
   return 0;
}
           

当上面的代码被编译和执行时,它会产生下列结果:

Memory size occupied by status1 : 8
Memory size occupied by status2 : 4
           

笔记:位数由0到32,增加4个字节。位数超过32,增加4个字节。即占用33位,消耗内存为8字节。

菜鸟教程展开>>

四、C语言实例

继续阅读