0

In many programming languages (including JavaScript, Java, and Ruby), it's possible to put an array inside itself. Here, I'm trying to put a C integer array inside itself at its 3rd index, but I'm not sure if this is supported in the C programming language:

#include <stdio.h>

int main(void) {
    int arr[] = {1, 1, 2};
    arr[2] = arr; //now I'm trying to put arr into itself.
    printf("%i", arr[2]); //this prints a negative number each time I run the program
    printf("%i", arr[2][0]); //prog.c:7:24: error: subscripted value is neither array nor pointer nor vector

    return 0;
}

Is it possible to put a C array inside itself, or is it not possible at all?

Community
  • 1
  • 1
Anderson Green
  • 30,230
  • 67
  • 195
  • 328
  • Make a jagged array if you need an array of arrays of different lengths. – chris May 22 '13 at 02:45
  • @chris Still, I don't see how that would make it any easier to put the array inside itself. – Anderson Green May 22 '13 at 02:46
  • 1
    You can make an array of void pointers and use lots of typecasting to drive yourself insane... Perhaps what you want instead is a linked list? – Paul May 22 '13 at 02:48
  • You probably could with an array of void pointers, but ... why? – John May 22 '13 at 02:49
  • @AndersonGreen, It's fairly easy if you assign to a pointer. If you want copies, it's not much more work. The thing is that C is not at all like Java, and definitely not like Ruby or JS. I find newer languages tend to have certain things built in that C doesn't and a lot of them tend to fix things that C makes harder than most languages now, like string operations. – chris May 22 '13 at 02:49
  • @John Representing a self-similar fractal is the main use case that I have in mind, since fractals usually contain copies of themselves. – Anderson Green May 22 '13 at 02:50
  • As Paul suggested, why not use linked lists? – Anish Ramaswamy May 22 '13 at 04:43

2 Answers2

5

No, it's not possible for an array of int to contain itself.

There are some (likely non-portable) tricks you can play, like making one of the elements of the array be a converted pointer to the array:

int arr[10];
arr[5] = (int)arr;

but this doesn't make the array contain itself. The expression arr, since it's of array type, is implicitly converted ("decays") to a pointer to its first element in most contexts, including this one. So, assuming the conversion doesn't lose any information, you can retrieve a pointer to the first element of arr by converting arr[5] back to type int*. Note that this only gives you a pointer to arr's first element; it loses any information about the length of arr. And it's very common for an int* pointer value not to fit into an int without loss of information (on 64-bit systems, it's common for int* to be 64 bits and int to be 32 bits).

Integers, pointers, and arrays are three very different things. They are not simply interchangeable.

Recommend reading: section 6 of the comp.lang.c FAQ; it does a very good job of explaining the often confusing relationship between arrays and pointers in C.

Even in languages like Java and Ruby, an array can't actually contain itself. It can contain a reference to itself -- though the language might provide syntactic sugar that hides the fact that it's a reference. In C, such references are generally explicit.

What you can do is define a data structure that contains a pointer to an object of its own type. This is generally done with structures. For example:

struct tree_node {
    int data;
    struct tree_node *left;
    struct tree_node *right;
};

This being C, you have to manage memory for your tree nodes explicitly, using malloc() to allocate and free() to deallocation -- or you can use an existing library that does that for you.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

It actually is possible, if the length of an int on your system is equal to or greater than the length of a pointer, such that you can cast the pointer to an int to store it - and if you remember to cast it back before you try to dereference it as a pointer. Neglecting to do the latter was the cause of your error message.

Note that in such a simple scheme you will have to separately keep track of which elements are values and which are pointers. Only if you can guarantee that the length of a pointer is less than the length of an element (or that the valid range of a userspace pointer is further constrained) could you reserve some bits to indicate if an element is a literal value or a pointer.

Here's an example of how you might explicitly cast it back, based on prior knowledge that this is what would be appropriate for that element:

printf("%i", ((int *)arr[2])[0]);

To accomplish this more cleanly, you may want to make an array not of ints, but instead of unions, such that each element is a union of an int and a pointer - meaning there are two formally recognized possible views of the same memory. But you will still need a scheme to keep track of the applicable type of each element.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117