【问题标题】:Passing the address of a dereferenced pointer to a string offset将取消引用的指针的地址传递给字符串偏移量
【发布时间】:2019-07-31 06:28:27
【问题描述】:

假设有这样的函数

int foo (char** str, int x)
{
    char* p = *str + x;

    foo2(&p); // declared as int foo2 (char** );
}

(当然过于简单了,真正的函数是递归的,而且要复杂得多)


我试过这样做:

int foo (char** str, int x)
{    
    foo2(&(*str + x));
}

但是编译失败并出现错误:

错误:需要左值作为一元“&”操作数

为什么编译器会出现这个错误,我如何将指针传递给指向字符串 x-byte(s) 转发的指针,而不声明变量并使用它自己的地址?


编辑

似乎有一些误解,所以我将发布一个完整的模拟我想要实现的目标。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* string = "This is a sample string.";
char* ptr;
int randomizer;

int receive_string (char* buffer, int size) // recv
{
    int i = 0;

    if(ptr == NULL)
        ptr = string;

    for(i = 0; *ptr != '\0' && i < size; ptr++)
    {
        if(randomizer == 2)
        {
            randomizer++;

            break;
        }

        buffer[i] = *ptr;

        i++;

        randomizer++;
    }

    if(*ptr == '\0')
    {
        buffer[i] = *ptr;

        i++;
    }

    return i;
}

int read_string (char* *buffer, int size, int alloc)
{
    int bytes = 0;

    printf("Reading string..\n");

    if(*buffer == NULL && alloc == 1)
    {
        printf("Allocating buffer..\n");

        *buffer = calloc(size, sizeof(char));
    }

    bytes = receive_string(*buffer, size);

    if(bytes == (-1))
    {
        return(-1);
    }
    if(bytes == 0)
    {    
        return 0;
    }
    if(bytes < size)
    {
        char* p = *buffer + bytes;
        //int temp = read_string(&p, size - bytes, 0); // works
        //int temp = read_string(&(char *){&(*buffer)[bytes]}, size - bytes, 0); // works
        int temp = read_string(buffer + bytes, size - bytes, 0); // doesn't work

        if(temp > 0)
            bytes += temp;
        else return bytes;
    }

    return bytes;
}

int main()
{
    char* buffer = NULL;

    int bytes = read_string(&buffer, strlen(string) + 1, 1);

    printf("[%u][%s]\n", bytes, buffer);

    if(buffer)
        free(buffer);

    return 0;
}

randomizer 是“模拟”无法接收所有字节的recv() 的最愚蠢的快捷方式。此实现模拟recv(),但不是从套接字队列中读取,而是从全局字符串中读取。

【问题讨论】:

  • @machine_1 编辑了问题以澄清foo2() 具有相同的参数集。这就是为什么我说原始函数是递归的。但是,如果我要制作这样的示例,我将不得不抛出更多的代码来提供一个可以工作而不是死锁的代码,这不是最小的。
  • 星星太多。不要成为三星级程序员。如果一个函数分配了,让它返回一个指针。
  • 那么为什么不让它返回缓冲区并通过引用传递大小呢?连续的星星越少,越容易理解。有时你当然必须这样做。
  • 这毫无意义。你为什么要这样做?
  • @Edenia 但是你发布了代码,它有free(*buffer);

标签: c algorithm pointers pointer-arithmetic


【解决方案1】:

如果你想将指针传递给指向特定字符的指针

foo2(&(char *){&(*str)[x]});

【讨论】:

  • @n.m. - 这是一个复合文字,而不是命名变量。但我同意这不太可能通过代码审查。
  • @P__J__ 我知道语法。这里不需要。它唯一能做的就是搅浑水。
  • 可能是正确的。可读且易于维护,但事实并非如此。所以我会在代码审查中拒绝它而支持命名变量,因为两者将产生几乎相同的机器代码
  • @StoryTeller - 但问题是:如何没有这条附加线。您的意见并不重要,因为问题是如何避免这条线。我的回答实际上是给出了正确的解决方案。那些 cmets 不在问题主题范围内。
  • @n.m.两者都是错误的,因为 OP 想要 char ** 而不是 char * - 所以我担心你错了。
【解决方案2】:

(*str + x) 不是左值,因为它是一个没有地址的临时值,因此您不能使用&amp; 获取其地址。即使编译器将值存储在 RAM 中的临时变量中,因此可以获取其地址,如果 foo2() 修改了临时变量的内容,那么之后您将如何引用它的值。

因此,您需要自己将值存储在临时变量中。

【讨论】:

  • 除了另一个答案显示了如何在不声明变量的情况下,而是作为文字。
  • @Edenia 另一个答案欺骗编译器允许它编译但不能解决如果 foo2() 修改str 时读取修改值的问题,这可能是传递的全部要点一个指向指针的指针,而不是仅仅传递一个指针。
  • @machine_1 不。因为这是指向字符串指针的指针算术,不是吗?令人困惑。
  • @Dipstick 如果内部函数只读取值,是不是可以?
  • @Edenia 另一个答案在堆栈上创建一个匿名临时变量,并将该变量的地址传递给foo2
【解决方案3】:

我认为下面的代码是你想要做的。为了踢球,我使它递归并用字母表测试它的字符串。变量 cnt 和 lmt 需要是全局的。如果你运行它,它会显示一个缩小的字符串。只要确保 p 和 lmt 足够小,不会溢出字符串。

void foo(char *s, int p) {
    cnt++;
    printf("%s\n", s);
    if(cnt != lmt) foo(&s[p], p);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 2020-12-29
    • 1970-01-01
    相关资源
    最近更新 更多