2015-01-21 15 views
0

所以我想这是一个更具风格的问题。C:使用指针指向具有固定数量字符的数组的动态内存分配

我需要写入一个大小为3字节的元素的动态数组。 (像素大小为24bpp的位图)

所以,每个元素都必须是char [3]。 如果我想避免使用struct pixel{ char R, char G, char B},避免预处理语句的使用,是有可能把它写成

char* pixel[3] 

并在3*sizeof(char)步骤分配?

为了说明高度和宽度,我需要一个char **像素[3],并且必须在单个char步骤中进行分配才能使其成为char ***像素。

所以我想我正在寻找一种方法来避免使用指针指针指针。 谢谢!

+0

只要保留一个'char ** pixeels'并且每次你想重新分配乘以3。 – saadtaame 2015-01-21 11:12:36

+1

“预处理器语句”的用法? – Arashium 2015-01-21 11:15:18

+0

@saadtaame:有一个线阵列,为了说明宽度和高度,我已经有了一个指针指针,为每个像素分配3sizeof(char)都增加了必要性,这大大降低了代码的可读性和简单性。这对我的同事来说应该是容易理解的。 Arashium:将结构写入文件需要#pragma或_attribute_'s,这是gcc专用的,不会在不同的平台上编译。 – BigBadWolf 2015-01-21 11:19:42

回答

-2

如果你不想要结构,你不能避免写char***

但是你可以使用一个类型,使其更多时尚

所以最好的解决方案符合您的要求似乎是:

#include <stdlib.h> 

typedef char*** pixelmap_t; 

int main() { 

    int channels = 3, width = 10, height = 10; 

    pixelmap_t test = malloc(width*height*channels); 

    int x = 1, y = 2, channel = 0; 

    test[x][y][channel] = 3; 

    free(test); 

    return 0; 
} 

看来,我完全搞砸了。我混淆了以下两件事情:

  1. 在声明静态3D阵pixels[100][100][3],那么该类型是char***。它是内存中连续300个项目的一维数组。

  2. 在声明char***并分配在存储器300名中的项目,然后解除引用全部用pixels[x][y][z]语法结果的尺寸在derefrencing第一维度和解释在存储器中作为指针的值和derefrencing该指针,而不是计算正确在3D阵列中偏移。

这意味着,我忽视了,访问器的语法有两种不同的语义。第一个我将称为3D数组的语义为array ([x][y][z]),第二个为char***(我使用括号强调)调用((array[x])[y])[z]语义。

此代码剪切和工作(测试它) - 但不是使用堆内存。 对于堆内存,我不知道已经发布的那些解决方案(malloc(width*height*channels)和访问pixels[c + channels*(y + x*height)])。

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

int main() { 

    int channels = 3, width = 10, height = 10; 

    char test[width][height][channels]; 

    char *ptr = (char*) test; 
    for (int i = 0 ; i < channels * width * height ; i++) { 
    ptr[i] = (char) (i % 255); 
    } 

    for (int x = 0 ; x < width ; x++) { 
    for (int y = 0 ; y < height ; y++) { 
     for (int c = 0 ; c < channels ; c++) { 
      int d = (int) test[x][y][c]; 
      printf("%d %d - %d : %d\n", x, y, c, d); 
     } 
    } 
    } 

    return 0; 
} 
+3

只要假装指针是'char ***',就不能将3D数组制作成锯齿形数组。 – user694733 2015-01-21 11:26:09

+0

伟大而可读的解决方案,谢谢!但是,只有一个问题,我不需要在char **内单独分配char *来分配工作吗? (据我的理解),你的代码似乎分配了300次char *的类型,但留下char **和char *未分配。 (除非我只是困惑自己) – BigBadWolf 2015-01-21 11:31:02

+0

谢谢!我向你致敬,并感谢你,但是这种方法不适用于大尺寸,因为我的尺寸达到INT_MAX * INT_MAX。 (我知道制作尺寸很大但没有用,但它又是一项任务。) 所以我想我必须为char ***而定。 – BigBadWolf 2015-01-21 14:43:38

1

你可以用一维数组来模拟这个。假设你想分配一个wxh矩形的像素。你可以写。

char *pixels = (char *) malloc(w*h*3*sizeof(char)); 

现在的3个色字节的内存出现连续的,你可以使用一些算术访问任何细胞

你可以得到/定义的宏设置在电池(i,j)颜色通道:

#define r(p, i, j) ((p)[(3*((w)*(i)+(j)))]) 
#define g(p, i, j) ((p)[(3*((w)*(i)+(j)) + 1)]) 
#define b(p, i, j) ((p)[(3*((w)*(i)+(j)) + 2)]) 

调用看起来像r(pixels, 0, 1)

+0

1.你的转换应该是'(char *)',而不是'(char **)'和2.你不能通过方便的像素[x] [y] [channel]来访问'char *''句法。 – UniversE 2015-01-21 11:24:11

+0

已修复,谢谢!这是真的,但你可以写一行功能(或宏)来做到这一点。 – saadtaame 2015-01-21 11:24:53

+0

@UniversE您根本不能使用“方便的语法”,因为compler不知道3D数组的维度。 – user694733 2015-01-21 11:29:25

3

你的意思是的[0 ... 255]?

注意区别:

unsigned char *pixel[3] - >数组的指针为char

Vs的

unsigned char (*pixel)[3] - >指针字符

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

#define N 4 

int main(void) 
{ 
    unsigned char (*pixel)[3]; 

    pixel = malloc(sizeof(*pixel) * N); 
    pixel[0][0] = 0; 
    pixel[0][1] = 128; 
    pixel[0][2] = 255; 
    /* ... */ 
    pixel[3][0] = 0; 
    pixel[3][1] = 128; 
    pixel[3][2] = 255; 

    printf("R:%d G:%d B:%d\n", pixel[0][0], pixel[0][1], pixel[0][2]); 
    free(pixel); 
    return 0; 
} 

如果你不知道的数组N之前用手替换mallocrealloc