在C中是否有这种多维数组声明的简写

时间:2016-02-02 22:17:59

标签: c multidimensional-array

所以我有这段代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char field1[45];
char field2[444];
char *fields[] = {
    field1, field2
};
int main (int argc, char *argv[])
{
    sprintf(fields[0], "hello\n");
    printf(fields[0]);
}

我不需要使用field1和field2访问字段。有没有一些速记方式来做到这一点?我尝试了以下不起作用。

char *fields[] = { char[45], char[444] };

基本上我想我想要一个包含不同长度字符串的数组,而不必使用malloc。

4 个答案:

答案 0 :(得分:1)

我想你可能想要一个结构。

struct fields {
    char field1[45];
    char field2[444];
};

struct fields theFields[100];

我没有看到多维数组。

答案 1 :(得分:1)

  

基本上我想我想要一个包含不同长度字符串的数组,而不必使用malloc。

更确切地说,你想要一个&#34;锯齿状的&#34;数组,其中每个fields[i]物理大小可以不同(即fields[0]为8个字符的字符串保留足够的空间,fields[1]保留足够的空间对于20个字符的字符串等),您仍然需要常规的多维数组语法才能工作。

不幸的是,您无法使用常规数组声明语法。

如果你真的不想搞乱动态内存,可以尝试的一件事是设置一个大的1D数组作为后备存储,然后将指针存储到该数组中。这就是我刚刚蠢蠢的事情:

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

#define HUGE 128

static char backing_store[HUGE];
static size_t backing_store_used = 0;

char *add_string( const char *str )
{
  char *p = NULL;
  if ( strlen( str ) < HUGE - backing_store_used )
  {
    p = &backing_store[backing_store_used];
    strcpy( p, str );
    backing_store_used += strlen( str ) + 1;
  }
  return p;
}

int main( void )
{
  char *strs[5] = {NULL};

  strs[0] = add_string("foo");
  strs[1] = add_string("blurga");
  strs[2] = add_string("supercalifragilisticexpealidocious");

  for ( size_t i = 0; i < 3; i++ )
  {
    printf( "strs[%zu] = %s (%zu), strs[%zu][1] = %c\n", i, strs[i], strlen( strs[i] ), i, strs[i][1] );
  }

  int printed = 0;
  for ( size_t i = 0; i < HUGE; i++ )
  {
    if ( printed > 80 )
    {
      putchar( '\n' );
      printed = 0;
    }
    printed += printf( isprint( backing_store[i] ) ? "%c " : "'\\0%o' ", backing_store[i] );
  }

  putchar( '\n' );
  return 0;
}

这是输出:

[fbgo448@n9dvap997]~/prototypes/stringspace: ./stringspace
strs[0] = foo (3), strs[0][1] = o
strs[1] = blurga (6), strs[1][1] = l
strs[2] = supercalifragilisticexpealidocious (34), strs[2][1] = u
f o o '\00' b l u r g a '\00' s u p e r c a l i f r a g i l i s t i c e x p e a l
i d o c i o u s '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00'
'\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00'
'\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00'
'\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00'
'\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00'
'\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00' '\00'
'\00' '\00'

因此,您可以假装您的strs数组是一个不同物理长度的字符串数组。

显然,您需要进行一些分析,看看您需要多大才能为要保存的字符串的数量和长度进行后备存储。

这非常适合设置您不打算更改的字符串的静态列表。如果你想编辑不同长度的字符串,或删除字符串或类似的东西,这会让人感到不快,你基本上写了一个你自己的动态内存管理器的破碎版本,此时你可能会好好使用malloc和朋友。

答案 2 :(得分:1)

您所呈现的是多维数组声明。它是指向char的指针数组的声明,您恰好将其初始化为两个指针的数组,一个指向两个char数组中每个指针的第一个元素。 必须了解数组和指针不是同一个东西。在这种特殊情况下,一个结果是两个1D数组不保证在内存中相邻,也不在内存中以相同的顺序排列,因为它们的指针在数组中。

由于多维数组是其元素为数组的数组,因此作为推论,指针数组不是多维数组。数组类型值衰减到指针的事实可能会混淆情况,但它不会改变它。

现在回答你的实际问题,没有没有简便的方法来初始化一个指针数组,比如你提供的值与你提供的值相当。有效的指针指向某个东西,你必须在某个地方声明某些东西(否则)。,如注释中提到的@immibis和@ M.M先前的回答,你可以使用数组文字而不是命名数组。有关语法,请参阅@ M.M的答案。但是,我重申,这是一个指针数组,而不是2D数组。

正如其他答案已经观察到的那样,还有其他数据结构可以提供更多关于布局和排序的保证,也许其中一种可以更好地满足您的实际需求,但其中没有一种比您提供的更短。

  

基本上我想我想要一个包含不同长度字符串的数组,而不必使用malloc。

尽管有上述任何一项,但如果您提交的工作代码实际上符合您的目的,那么它就没有任何问题。但是,根据不同长度的字符串数组的含义,这可能是另一种选择:

char fields[2][444];

两个数组元素 - 每个数组包含444 char个 - 每个数组元素都可以容纳任意长度的字符串,最长可达443 chars,字符串取决于字符串终止符数组中的位置。你不打算使用第一个元素的399个字节并不一定是个大问题。

做这样的事情也可能很方便:

char fields[][444] = { "a short string", "a somewhat longer string, ya know" };

请注意,在这种情况下,引用的字符序列是成员数组的 initializers 。在这种情况下不涉及指针。

答案 3 :(得分:1)

你可以写:

char *fields[] = {
    (char[45]) { 0 },
    (char[444]) { 0 }
};

我建议不要使用这种设计,因为它很难执行检查,以至于你不会超越缓冲区。