C 指针基础知识用例子解释——第一部分

举报
Tiamo_T 发表于 2021/09/28 16:04:48 2021/09/28
【摘要】 任何在 Linux 环境下工作的人(不仅仅是开发人员),都应该了解 C 编程语言的基础知识并编写一些基本的 C 程序。这篇文章是我们正在进行的关于 C 编程语言的系列文章的一部分。指针的概念是 C/C++ 语言最强大的基础之一。通过指针,开发人员可以直接从他/她的代码中访问内存,这使得与内存相关的操作非常快。但是,一如既往,强大的力量伴随着巨大的责任。开发人员必须非常小心地使用指针,以避免一...

任何在 Linux 环境下工作的人(不仅仅是开发人员),都应该了解 C 编程语言的基础知识并编写一些基本的 C 程序。

这篇文章是我们正在进行的关于 C 编程语言的系列文章的一部分。

指针的概念是 C/C++ 语言最强大的基础之一。

通过指针,开发人员可以直接从他/她的代码中访问内存,这使得与内存相关的操作非常快。但是,一如既往,强大的力量伴随着巨大的责任。

开发人员必须非常小心地使用指针,以避免一些可能成为调试噩梦的问题。

在本文中,我们将通过 C 语言中的示例来研究指针的基本概念。

什么是指针?

与其他可以存储值的普通变量不同,指针是可以保存变量地址的特殊变量。由于它们存储变量的内存地址,因此指针通常被称为“指向变量”。让我们试着理解这个概念。


如上图所示:


  • 普通变量“var”的内存地址为 1001,值为 50。
  • 指针变量有自己的地址2047,但存储为1001,即变量“var”的地址

如何声明一个指针?

一个指针声明为:

<pointer type> *<pointer-name>

在上面的声明中:

  1. pointer-type :它指定指针的类型。它可以是int、char、float等。这个类型指定了这个指针可以存储其地址的变量的类型。
  2. 指针名称:它可以是用户指定的任何名称。从专业上讲,每个代码都遵循一些编码风格。指针名称通常以“p”开头或以“ptr”结尾

指针声明的一个例子可以是:

char *chptr;

在上面的声明中,'char' 表示指针类型,chptr 是指针的名称,而星号 '*' 表示 'chptr' 是一个指针变量。

如何初始化指针?

指针的初始化方式如下:

<pointer declaration(except semicolon)> = <address of a variable>

OR 

<pointer declaration> 
<name-of-pointer> = <address of a variable>

请注意,上面的变量类型应该与指针类型相同。(虽然这不是一个严格的规则,但对于初学者来说应该记住这一点)。

例如 :

char ch = 'c'; 
char *chptr = &ch; //initialize 

OR 

char ch = 'c'; 
char *chptr; 
chptr = &ch //initialize

在上面的代码中,我们声明了一个字符变量 ch 来存储值 'c'。现在,我们声明了一个字符指针 'chptr' 并用变量 'ch' 的地址初始化它。

请注意,'&' 运算符用于访问任何类型变量的地址。

如何使用指针?

指针可以在两种情况下使用。

上下文1:用于访问指针存储的内存地址的变量的地址。

再次考虑以下代码:

char ch = 'c'; 
   char *chptr = &ch;

现在,每当我们在上面两行之后的代码中引用名称“chptr”时,编译器都会尝试获取该指针变量包含的值,即指针指向的变量(ch)的地址。即'chptr' 给出的值将等于'&ch'。

例如 :

char *ptr = chptr;

'chptr' 持有的值(在这种情况下是变量 'ch' 的地址)被分配给新的指针 'ptr'。

上下文 2:用于访问指针存储其内存地址的变量的值。

继续上面使用的一段代码:

char ch = 'c';
char t;
char *chptr = &ch;
t = *chptr;

我们看到在上面的最后一行中,我们在指针名称之前使用了“*”。这个星号运算符有什么作用?

好吧,当应用于指针变量名称时(如上面的最后一行),此运算符会产生此指针指向的变量的值。这意味着,在这种情况下,'*chptr' 将产生 chptr 持有的地址中保存的值。由于 'chptr' 保存变量 'ch' 的地址并且 'ch' 的值为 'c',所以 '*chptr' 产生 'c'。

与指针一起使用时,星号“*”运算符也称为“值”运算符。

C 指针的一个例子

考虑以下代码:

代码 :

#include <stdio.h> 

int main(void) 
{ 
    char ch = 'c'; 
    char *chptr = &ch; 

    int i = 20; 
    int *intptr = &i; 

    float f = 1.20000; 
    float *fptr = &f; 

    char *ptr = "I am a string"; 

    printf("\n [%c], [%d], [%f], [%c], [%s]\n", *chptr, *intptr, *fptr, *ptr, ptr);

    return 0; 
}

输出 :

$ ./pointers 

 [c], [20], [1.200000], [I], [I am a string]

要调试 C 程序,请使用gdb。上面的代码涵盖了所有常见的指针。他们中的前三个现在很容易理解,所以让我们专注于第四个。在第四个例子中,一个字符指针指向一个字符串。

在 C 中,字符串只不过是一个字符数组。所以我们在 C 中没有凝视指针。它也是用于字符串的字符指针。

现在,谈到字符串,当我们将指针指向字符串时,默认情况下它保存字符串第一个字符的地址。让我们试着更好地理解它。

内存中的字符串 'I am String' 被放置为:

1001   1002    1003    1004   1005   1006   1007   1008   1009   1010
I      a       m       S      t      r      i      n      g      \0

由于每个字符占用一个字节,因此它们在内存中的放置方式如上。注意最后一个字符,它是一个空字符,在 C 中默认放置在每个字符串的末尾。这个空字符表示字符串的结尾。

现在回到重点,任何指向字符串的字符指针都存储字符串的第一个字符的地址。在上面的代码中,'ptr' 保存了字符 'I' 的地址,即 1001。现在,当我们将 'value of' 运算符 '*' 应用于 'ptr' 时,我们打算获取地址 1001 处的值,即'I' 因此当我们打印 '*ptr' 时,我们得到 'I' 作为输出。

此外,如果我们将格式说明符指定为 '%s' 并使用 'ptr'(包含字符串的起始地址),则使用 printf 打印完整的字符串。这个概念是 %s 说明符需要字符串的起始字节的地址来显示完整的字符串,我们使用 'ptr' 提供它(我们知道它保存字符串的起始字节地址)。我们可以将其视为上面输出中的最后一个打印。

指针作为结构对象

考虑以下代码:

代码:

#include<stdio.h> 

struct st{ 
int a; 
char ch; 
}; 

int main(void) 
{ 
    struct st obj; 
    struct st *stobj = &obj; 

    stobj->a = 5; 
    stobj->ch = 'a'; 

    printf("\n [%d] [%c]\n", stobj->a, stobj->ch); 
    return 0; 
}

输出:

$ ./pointers 

 [5] [a]

在上面的代码中,我们声明了一个“struct st”类型的指针 stobj。现在由于指针类型是一个结构,所以它指向的地址必须是一个“struct st”类型变量(在这种情况下是“obj”)。另一个有趣的部分是如何使用指针变量 'stobj' 访问结构元素。是的,在处理指针对象时,使用箭头运算符 -> 而不是 '.' 是一种标准。运算符(如果我们使用 'obj' 来访问结构元素,它会被使用)。

总而言之,在本文中,我们从头开始研究 C 中指针的概念,然后在我们对更复杂的主题(例如将指针用作结构对象)的理解的基础上慢慢建立。这是一个基础教程,我们将在本文的第二部分介绍更复杂的指针概念。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。