fork download
  1. #include <stddef.h>
  2. #include <stdlib.h>
  3.  
  4. /*** Constants */
  5. enum e_rgb {
  6. Red,
  7. Green,
  8. Blue,
  9. RGBCount
  10. };
  11.  
  12. /*** Object types */
  13. typedef unsigned char rgb[RGBCount];
  14.  
  15. /*** Function declarations */
  16. struct s_picture * alloc_picture(int w, int h);
  17. rgb * picture_row(struct s_picture * pic, int row);
  18.  
  19. /*** Struct/union definitions */
  20. struct s_picture {
  21. int width;
  22. int height;
  23. rgb * data;
  24. };
  25.  
  26. /*** Function definitions */
  27. int main(void) {
  28. struct s_picture * pic;
  29. rgb * row_ten;
  30.  
  31. /* Allocate a 10 x 10 picture */
  32. pic = alloc_picture(10, 10);
  33. if (!pic)
  34. return EXIT_FAILURE;
  35.  
  36. /* Produce a pointer to the tenth row */
  37. row_ten = picture_row(pic, 9);
  38.  
  39. /* The next three sections all do the same thing */
  40. Red[*row_ten] = 42;
  41. Green[*row_ten] = 42;
  42. Blue[*row_ten] = 42;
  43.  
  44. row_ten[0][Red] = 42;
  45. row_ten[0][Green] = 42;
  46. row_ten[0][Blue] = 42;
  47.  
  48. (*row_ten)[Red] = 42;
  49. (*row_ten)[Green] = 42;
  50. (*row_ten)[Blue] = 42;
  51.  
  52. /* Clean-up and terminate */
  53. free(pic);
  54. return EXIT_SUCCESS;
  55. }
  56.  
  57. /* Allocate storage for a picture */
  58. struct s_picture * alloc_picture(int w, int h) {
  59. /* Wrap up a picture */
  60. struct s_wrapper {
  61. struct s_picture pic[1];
  62. /* This member is here for alignment */
  63. rgb data[1];
  64. };
  65. size_t size;
  66. void * ptr;
  67. struct s_wrapper * wrapper;
  68. unsigned char * bytes;
  69.  
  70. /* Compute the amount of storage to allocate */
  71. size = (
  72. /* Don't allocate for the alignment member */
  73. offsetof(struct s_wrapper, data)
  74. + sizeof wrapper->data * w * h
  75. );
  76. if (size < sizeof *wrapper)
  77. size = sizeof *wrapper;
  78.  
  79. /* Allocate the storage */
  80. ptr = malloc(size);
  81. /* Return a null pointer on failure */
  82. if (!ptr)
  83. return ptr;
  84.  
  85. wrapper = ptr;
  86. bytes = ptr;
  87.  
  88. wrapper->pic->width = w;
  89. wrapper->pic->height = h;
  90.  
  91. /* There is a problem with the next line */
  92. wrapper->pic->data = wrapper->data;
  93. /*
  94.   * Since there is only one element for 'wrapper->data',
  95.   * that means that the pointer value yielded by that
  96.   * expression could have such bounds associated with it.
  97.   * Instead, we derive a pointer value from 'bytes', whose
  98.   * bounds would be those of the call to 'malloc', above
  99.   */
  100. wrapper->pic->data = (rgb *) (bytes + offsetof(struct s_wrapper, data));
  101. /* That was safer */
  102.  
  103. return wrapper->pic;
  104. }
  105.  
  106. /* Produce a pointer to the specified row in a picture */
  107. rgb * picture_row(struct s_picture * pic, int row) {
  108. return pic->data + row * pic->width;
  109. }
  110.  
Success #stdin #stdout 0.01s 1848KB
stdin
Standard input is empty
stdout
Standard output is empty