使用带有字符类型变量的指针

Using pointers with char type variables

本文关键字:类型变量 指针 字符      更新时间:2023-10-16

我正在学习使用C++对微控制器进行编程。NewbieHack.com有一个很棒的教程,但我一直停留在处理指针的部分。

在他的代码中,他编写了一个名为Send_a_String 的函数

void Send_A_String(char *StringOfCharacters)
{
   while(*StringOfCharacters > 0)
   {
     Send_A_Character(*StringOfCharacters++);
   }
}

在代码的int main()部分中,他以以下方式调用函数

 Send_A_String("NewbieHack.com");

"NewBieHack.com"的使用让我感到困惑,因为函数的输入是一个char类型的变量。如何使用指针将字符串分配给字符类型的变量?

如果措辞不明确,我深表歉意。如有任何帮助,我们将不胜感激。

这之所以有效,是因为"NewbieHack.com"是一个空终止的字符数组,可以可视化为{'N', 'e', 'w', 'b', 'i', 'e', 'H', 'a', 'c', 'k', '.', 'c', 'o', 'm', ''}

因此,当您调用Send_A_String("NewbieHack.com")时,常量字符串"NewbieHack.com"将被强制转换为指向char数组开头的const char*(在本例中为'N')。

在while循环中,您将迭代char数组,直到到达char数组的末尾(即"\0")。

尽管这是可疑的,根据polkadotcadaver的评论,我会解释。

(未固定)字符串文字的类型实际上是const-char[],而不是std::String。当函数被调用时,char[]实际上会衰减为char*。Send_A_String不是常量正确的(因为它确实应该接受常量char*),但这可能只会导致编译器发出警告。

请注意,输入不是字符类型变量,而是指向字符类型变量的指针!这让一切变得不同。因此const char[]"NewbieHack.com"衰减为const char*,它与char*兼容。

现在指针指向char[]的第一个字符,即'N'。由于它是一个指针,您需要使用运算符*来取消对它的引用,以便获取字符。

循环测试字符串结尾("\0"),然后调用带有取消引用的指针(即指针指向的字符)的Send_A_Character,并将指针前进一个。因此,指针现在指向char[]的第二个字符"e"。以此类推,直到到达终点。

写入:

Send_A_String("NewbieHack.com");

实际上和写在下面是一样的

const char* sz = "NewbieHack.com";
Send_A_String(sz); // with dangerous conversion const char* -> char*

更正确的版本是:

char sz[] = "NewbieHack.com";
Send_A_String(sz);

至少不应该发出任何警告。但实际上Send_A_String应该将其参数更改为constchar*,因为它不会更改字符串字符,而只是递增指针。

[编辑]

如果让你困惑的是下面这行:

 Send_A_Character(*StringOfCharacters++);

然后你可以重写如下:

StringOfCharacters++; // increment pointer to next char
char c = *StringOfCharacters; // dereference pointer to get char
Send_A_Character(c); // use char

现在应该很容易理解发生了什么

发生的事情是这样的。

"NewbieHack.com"实际上是指向编译器以null结尾的字符串(或数组)的指针。它位于给定地址的某个RAM段中,例如

0xface0000 = 4E 65 77 64 69 65 48 61   N  e  w  b  i  e  h  a
0xface0008 = 63 6B 2e 63 6f 6D 00      c  k  .  c  o  m   

调用示例中的函数时

Send_A_String("NewbieHack.com");

编译器正在将地址传递给函数。因此,Send_A_String循环遍历字符串中的字符,将它们打印出来,直到遇到null字符(或0)。

这里的语法有一个微妙的差异,这很重要。在列出参数的函数定义中,'char*StringOfCharacters'表示StringOfCharacters是指向字符的指针(地址)。稍后,语法(*StringOfCharacters>0)表示尊重变量StringOfCharacters中包含的地址,并使用其中的值。在这两种情况下,使用"*"的含义并不相同。我看看我是否能举例说明:

void Send_A_String(char *StringOfCharacters) /* StringOfCharacters = 0xface0000 */
{
   while(*StringOfCharacters > 0)
   /* iteration 1  : *0xface0000 = 0x4E or 'N' so print it out below */
   /* iteration 2  : *0xface0001 = 0x65 or 'e' so print it out below */
   /* iteration 3  : *0xface0002 = 0x4E or 'w' so print it out below */
   ...
   /* iteration 15 : *0xface000e = 0x00 or 0 or NULL so stop */
   {
     Send_A_Character(*StringOfCharacters++);
     /* here the *StringOfCharacters gets done first */
     /* the ++ is applied after the function returns */
     /* iteration 1  : print 'N' then increment, StringOfCharacters now = 0xface0001 */
     /* iteration 2  : print 'e' then increment, StringOfCharacters now = 0xface0002 */
     /* iteration 3  : print 'w' then increment, StringOfCharacters now = 0xface0003 */
     ...
     /* iteration 14 : print 'm' then increment, StringOfCharacters now = 0xface000e */
   }
}

希望能有所帮助。

它不是字符类型。它是指向字符char *的指针。你可以看到一个指针作为数组的起始地址,所以你基本上有一个char数组,witch实际上是一个字符串。

这里的*StringOfCharacters取消引用指针,意思是地址StringOfCharacters处的字符。

*StringOfCharacters++这必须一分为二:StringOfCharacters++递增指针,所以现在指针指向数组中的下一个字符(请注意,这是指针算法),但由于它是运算符后缀增量,它将返回下一部分的旧指针值:*StringOfCharacters开关再次取消指针的引用,给你一个字符。希望我是清白的。

此函数无效。首先呼叫

 Send_A_Character(*StringOfCharacters++);

不应编译因为表达式*StringOfCharacters++不是指针。此外,没有任何意义的调用(如果上面的调用包含拼写错误)

 Send_A_Character(StringOfCharacters++);

因为你会得到堆栈溢出。

还有这种情况

while(*StringOfCharacters > 0)

应该改为

while( *StringOfCharacters )

because类型的char可以表现为签名的char。

我会用以下方式重写函数

void Send_A_String( const char *StringOfCharacters )
{
   while ( *StringOfCharacters )
   {
     Send_A_Character( ++StringOfCharacters );
   }
}

编辑:对不起。我没有看到有两个不同的函数Send_A_String和Send_A_Character。:)所以我按照的方式改变了功能

void Send_A_String( const char *StringOfCharacters )
{
   while ( *StringOfCharacters )
   {
     Send_A_Character( *StringOfCharacters++ );
   }
}