将指针视为数组合法吗? void uc(字符*s) { int i; 对于(i=0;i

将指针视为数组合法吗? void uc(字符*s) { int i; 对于(i=0;i,c,arrays,pointers,C,Arrays,Pointers,s是一个指针,因此如果分配了它,我们可以将其用作数组 以下两个选项类似: void uc(char* s) { int i; for( i=0; i < strlen(s); i++ ) if (97 <= s[i] && s[i] <= 122) s[i] = s[i] - 32; return; } 及 因为内存地址是十六进制格式的整数(对吗?) 不,用户使用十六进制格式来显示内存地址。如

s
是一个指针,因此如果分配了它,我们可以将其用作数组

以下两个选项类似:

void uc(char* s)
{
    int i;

    for( i=0; i < strlen(s); i++ )
        if (97 <= s[i] && s[i] <= 122)
            s[i] = s[i] - 32;

    return;
}

因为内存地址是十六进制格式的整数(对吗?)

不,用户使用十六进制格式来显示内存地址。如果使用二进制数来描述内存地址,它太长了。

char*s
复制数组-不,它不复制

此函数的参数是指向
char
的指针。就是这样。指针的取消引用语法可以有两种形式:
*(p+n)
,和
p[n]
。这两种形式是等效的。在这两种情况下,
p
中的地址都是按值获取的,并使用元素类型的跨距进行调整,然后根据使用上下文取消对结果地址的引用以进行读取或存储

你的函数可以用一种更加明显的方式编写,作为奖励,每次迭代都要避免
strlen
调用(这可能会很昂贵)

将在符合ascii标准的平台上打印
LOWER
。我恳请您在调试器中运行上述代码,并注意以下事项:

  • main()中
    s[]
    的基址
  • 初始进入时,
    uc
    的参数列表中
    s
    的值
  • 循环迭代时,
    uc
    中的
    s
    会发生什么变化
  • 在各种上下文中使用时,
    *s
    的值出现在
    uc

老实说,这是我能做的最好的解释了。祝你好运。

首先要做的事,而且要完全直言不讳:

你的思维模式是错误的!在你陷入太深的思维模式之前,现在纠正你的错误观念是势在必行的

char*s
复制数组

这是一种误解。
s
是指向
char
的指针。它可以是单个
char
或整个数组。获取地址时,底层对象的确切类型将丢失

不过,没有复制任何东西!它只是一个指向“where”(挥舞手臂)的指针,所有相关人员(您、编译器、其他程序员)都达成了一个默契和不成文的协议,即友好而不做愚蠢的事情。比如传入一个指针,该指针稍后将在函数中以无效方式使用

这是正常的,因为数组名是它的第一个元素内存地址

数组没有名称!符号有名称。数组的符号将衰减为指向构成数组的基本类型的指针。这就是为什么您可以编写
char-somearray[123];char*p=somearray
,而无需获取其地址

为什么我们在for循环中将指针s视为数组

因为我们可以。更具体地说是因为这个叫做“指针算术”的东西。expression
s+1
将产生一个指针,指向一个元素,超过指针指向的元素的地址。它适用于任何数字(在
ptrdiff\u t
的值范围内)

当你用C写
a_指针[i]
时,它会逐字翻译成
*(a_指针+i)
。因此,通过写
a_指针[i]
你告诉编译器:*“假设
a_指针
指向数组对象,并且
a_指针+i
仍在该数组对象的边界内:根据该假设,取消对该位置的引用并在该位置生成值。”

但是仅当生成的指针位于对象的边界内时,才定义指针算法的结果

对不是从数组中获取的指针执行指针算术吗?未定义

生成超出数组边界的指针?未定义

我的问题是,我认为它们是“int变量”,

它们不是!从技术上讲,指针可能是由unicorn dust和magic实现的。当它们与数字混合时,有一些非常具体的规则。在C编程语言中,这些规则是(简化的):

  • 指针可以转换为大小为
    sizeof(uintpttr\u t)
    的整数,反之亦然

  • 数值0转换为空指针,空指针转换为数值0

  • 空指针无效,因此不能取消引用

  • 指针可以相互相减,得到一个与
    ptrdiff\u t
    兼容的整数,并且得到的整数的值是这两个指针之间的元素距离,假设两个指针引用同一个对象。用“类型”编写
    ⟪ptrdiff\t⟫ = ⟪指针A⟫ - ⟪指针B⟫,仅此的算术有效重排有效

  • 不能添加指针

  • 你不能增加指针

  • 没有规定指针的数字表示可以用于指针算术。也就是说,对于
    k
    的任何值,都不能假定
    (指针A-指针B)=k*((uintptr\t)指针A-(uintptptr\t)指针B))

由于内存地址是十六进制格式的整数(对吗?)

哈?!?事情不是这样的

是的,您可以使用整数来寻址内存位置。不,您不必将它们写为十六进制。十六进制只是一个不同的基数,0xF==15=0o17==0b1111。现在我们通常用十六进制来写地址,因为它与我们当前计算机体系结构的字大小(2.1十六进制d的幂)非常吻合igit等于4位,但t
s[i] = s[i] - 32;
*(s+i) = *(s+i) -32
void uc(char* s)
{
    for (; *s; ++s)
    {
        if (97 <= *s && *s <= 122)
            *s -= 32;
    }
}
#include <stdio.h> // for puts

void uc(char* s)
{
    for (; *s; ++s)
    {
        if (97 <= *s && *s <= 122)
            *s -= 32;
    }
}

int main()
{
    char s[] = "lower";
    uc(s);
    puts(s);
    return 0;
}
char foo[] = "hello";
        +–––+
0x1000: |'h'|
        +–––+
0x1001: |'e'|
        +–––+
0x1002: |'l'|
        +–––+
0x1003: |'l'|
        +–––+
0x1004: |'o'|
        +–––+
0x1005: | 0 |          
        +–––+
uc( foo );
void uc( char *s ) { ... }
a[i] == *(a + i)
int vector[N]; // for some value of N
void foo( T x ) // for any type T
{ 
  x = new_value;
}

void bar( void )
{
  T var;
  foo( var );
}
void foo( T *ptr )
{
  *ptr = new_value; // write a new value to the thing ptr *points to*
}

void bar( void )
{
  T var;
  foo( &var ); writes a new value to var
}
*ptr ==  var  // T   == T
 ptr == &var  // T * == T *
int x;
int *ptr = &x; // ptr is *not* being dereferenced
int y = 5;
*ptr = y;      // ptr *is* being dereferenced