C中的指针声明,有什么区别?

Pointer declaration in C, whats the difference?

我认为#1

uint8_t* start_ptr, end_ptr;

和#2

uint8_t* start_ptr;
uint8_t* end_ptr;

大体相同。在我看来他们不是。 有人可以指定第一个除了第二个以外的功能吗?

发生了什么:

          if(strncmp(mseq,mseq_a,8) == 0){
              start_ptr = MY_UART_RingBuffer_getReadPointer();
              start_found = 1;

          }

          if(strncmp(mseq+3,mseq_z,5) == 0){
              end_ptr = MY_UART_RingBuffer_getReadPointer();

              if (start_found == 1){
                  if(!MY_UART_RingBuffer_getOverlap()){
                    end_ptr = end_ptr - 6;
                  }
                  else{
                      start_found = 0;
                      continue;
                  }

                ptrdiff_t length = end_ptr - start_ptr;
                  start_found = 0;
              }
          }

在使用#1 时,编译器会给我这样的长度计算:

../Core/Src/main.c:143:32: error: invalid operands to binary - (have 'int' and 'uint8_t * {aka unsigned char *}')
     ptrdiff_t length = end_ptr - start_ptr;

使用#2 一切正常。

我在这里有点困惑。我看到了解决方案,但我并没有真正理解问题所在。

非常感谢 ;-)

在语法上,类型 uint8_t 是一个 声明说明符 ;而指针 * 是一个 声明符 According to C's grammar declarators 绑定到声明的名称而不是 declaration-specifier。因此,您的第一行被解析为:

uint8_t (*start_ptr), end_ptr;

即只有名字成为指针。

这是一些人倾向于将 space 放在指针 * 之前而不是之后的原因之一。在一行中声明它们的正确方法是:

uint8_t *start_ptr, *end_ptr; // both are pointers to uint8_t.

这个声明

uint8_t* start_ptr, end_ptr;

可以等效地重写为

uint8_t ( * start_ptr ), ( end_ptr );

所以声明了uint8_t *类型的指针start_ptruint8_t类型的变量end_ptr

如果你想声明两个指针你必须写

uint8_t *start_ptr, *end_ptr;

另一种方法是使用 typedef 声明引入新的类型说明符,例如

typedef uint8_t * uint8_t_ptr;

使用声明的 typedef 名称你可以写

uint8_t_ptr start_ptr, end_ptr;

在这种情况下,两个声明的变量都将具有指针类型 uint8_t *

C 中的声明由两个主要部分组成 - 一系列 声明说明符 ,后跟逗号分隔的 声明符列表 。指针性、数组性和函数性被指定为声明符的一部分,因此您的声明被解释为

uint8_t (*start_ptr), end_ptr;

并且只有 start_ptr 被声明为指针。

想法是声明符的结构与代码中表达式的结构相匹配。当您想要访问 start_ptr 指向的 uint8_t 值时,您可以使用一元 * 运算符取消引用它:

x = *start_ptr;

表达式*start_ptr的类型是uint8_t,所以声明写成

uint8_t *start_ptr;

空格除了区分相同类型的标记外没有其他意义。由于 * 不能是任何标识符的一部分,您可以将该声明写为

uint8_t *start_ptr;
uint8_t* start_ptr;
uint8_t*start_ptr;
uint8_t     *    start_ptr   ;

但它将始终被标记为 uint8_t*start_ptr;,并解析为

uint8_t (*start_ptr);

所以如果你想将 start_ptrend_ptr 都声明为指针,那么你需要写成

uint8_t *start_ptr, *end_ptr;

uint8_t *start_ptr;
uint8_t *end_ptr;

换句话说,我们将指针声明为

T *p, *q;

出于完全相同的原因,我们将数组声明为

T[N] a, b;

因为后缀[]下标运算符的操作数是ab,不是T,而一元 (hint hint hint) *运算符是pq,不是T.