将取消引用的指针的地址传递给字符串偏移量
Passing the address of a dereferenced pointer to a string offset
假设有这样一个函数
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));
}
但编译器因错误而失败:
error: lvalue required as unary '&' operand
为什么编译器会抛出此错误?如何将指针传递给指向字符串 x 字节的指针,而不声明变量并使用其自己的地址?
编辑
好像有一些误解,所以我会post一个完整的模拟我想要达到的目标。
#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 != '[=12=]' && i < size; ptr++)
{
if(randomizer == 2)
{
randomizer++;
break;
}
buffer[i] = *ptr;
i++;
randomizer++;
}
if(*ptr == '[=12=]')
{
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
是 "simulate" 无法接收所有字节的 recv()
的最愚蠢的快捷方式。此实现模拟 recv()
,但不是从套接字队列中读取,而是从全局字符串中读取。
如果你想将指针传递给指向特定字符的指针
foo2(&(char *){&(*str)[x]});
或
(*str + x)
不是左值,因为它是一个没有地址的临时值,所以你不能用 &
获取它的地址。即使编译器将值存储在 RAM 中的临时变量中以便可以获取其地址,如果 foo2() 修改了临时变量的内容,您将如何在之后引用其值。
因此您需要自己将值存储在一个临时变量中。
我认为以下代码是您要执行的操作。为了好玩,我让它递归并用字母表测试它的字符串。变量 cnt 和 lmt 需要是全局的。如果你 运行 它会显示一个收缩的字符串。请务必保持 p 和 lmt 足够小以免溢出字符串。
void foo(char *s, int p) {
cnt++;
printf("%s\n", s);
if(cnt != lmt) foo(&s[p], p);
}
假设有这样一个函数
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));
}
但编译器因错误而失败:
error: lvalue required as unary '&' operand
为什么编译器会抛出此错误?如何将指针传递给指向字符串 x 字节的指针,而不声明变量并使用其自己的地址?
编辑
好像有一些误解,所以我会post一个完整的模拟我想要达到的目标。
#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 != '[=12=]' && i < size; ptr++)
{
if(randomizer == 2)
{
randomizer++;
break;
}
buffer[i] = *ptr;
i++;
randomizer++;
}
if(*ptr == '[=12=]')
{
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
是 "simulate" 无法接收所有字节的 recv()
的最愚蠢的快捷方式。此实现模拟 recv()
,但不是从套接字队列中读取,而是从全局字符串中读取。
如果你想将指针传递给指向特定字符的指针
foo2(&(char *){&(*str)[x]});
或
(*str + x)
不是左值,因为它是一个没有地址的临时值,所以你不能用 &
获取它的地址。即使编译器将值存储在 RAM 中的临时变量中以便可以获取其地址,如果 foo2() 修改了临时变量的内容,您将如何在之后引用其值。
因此您需要自己将值存储在一个临时变量中。
我认为以下代码是您要执行的操作。为了好玩,我让它递归并用字母表测试它的字符串。变量 cnt 和 lmt 需要是全局的。如果你 运行 它会显示一个收缩的字符串。请务必保持 p 和 lmt 足够小以免溢出字符串。
void foo(char *s, int p) {
cnt++;
printf("%s\n", s);
if(cnt != lmt) foo(&s[p], p);
}