int* myPointer = new int[100];
// ...
int firstValue = *(myPointer + 0);
int secondValue = myPointer[1];
Is there any functional difference between *(myPointer + index) and myPointer[index]? Which is considered better practice?
Functionally, they are identical.
Semantically, the pointer dereference says "Here's a thing, but I really care about the thing X spaces over", while the array access says "Here's a bunch of things, I care about the Xth one."
In most cases, I would prefer the array form.
There is no difference between
*(array+10); //and
array[10];
but guess what? since + is commutative
*(10 + array); //is all the same
10[array]; //! it's true try it !
No, they are functionally equivalent.
First, index is scaled up to the type size then added to the myPointer base, then the value is extracted from that memory location.
The "better practice" is the more readable one, which is usually, but not necessarily always, the myPointer[index] variant.
That's because you're usually interested in an element of the array, not the memory location to dereference.
There is no functional difference I know of but the form myPointer[1] is ultimately more readable and far less likely to incur coding errors.
DC
The form *(myPointer + 1) does not allow for changing the type of pointer to an object and therefore getting access to the overloaded [] operator.
Also debugging is far harder
int *ints[10];
int myint = ints[10];
is easier to pickup visually than
int *ints;
int myint = *(ints + 10);
also the compiler can insert range checking to catch the error at compile time.
DC
More readable and more maintainable code is better code.
As for functional part... There is no difference. Both times you are "playing with memory".
There is no functional difference. The decision to use either form is usually made depending on the context in which you are using it. Now in this example, the array form is simpler to use and read and hence is the obvious choice. However, suppose you were processing a character array, say, consuming the words in a sentence. Given a pointer to the array you might find it easier to use the second form as in the code snippet below:
int parse_line(char* line)
{
char* p = line;
while(*p)
{
// consume
p++;
}
...
}
Edit 1 : Decade-old question. But still, I think this answer will help to know the compiler's perspective.
Compiler creates the same machine code for both cases. here's a proof,
code 1
#include<stdio.h>
int main()
{
int myArr[5] = {1, 2, 3, 4, 5};
int value = myArr[0];
}
code 2
#include<stdio.h>
int main()
{
int myArr[5] = {1, 2, 3, 4, 5};
int value = *(myArr + 0);
}
Below is the result of the comparison done on assembly code generated by compiling the C code of both the codes with gcc -S.
Actually , When an Array 'a' is initialized a pointer to its first memory location ie.. a[0] is returned which is nothing but a ;
So if you do 'a+1' it is actually a pointer to a[1]
if you do 'a+2' it is actually a pointer to a[2]
if you do 'a+3' it is actually a pointer to a[3]
so on ,
so if you do *(a+1) you will get value of a[1] and similar for other values also.
if you do *(a) you actually get a[0],
So i think its pretty clear now how it works..
Related
If I define an variable:
int (**a)[30];
It is pointer. This pointer points to a pointer which points to an array of 30 ints.
How to declare it or initialize it?
int (**a)[10] = new [10][20][30];
int (**a)[10] = && new int[10];
All doesn't work.
The direct answer to your question of how to initialize a (whether or not that's what you actually need) is
int (**a)[10] = new (int (*)[10]);
I don't think this is actually what you want though; you probably want to initialize the pointer to point to an actual array, and either way std::vector is the better way to do it.
If you want an answer to the question as it stands, then you can do this kind of thing:
int a[30];
int (*b)[30] = &a;
int (**c)[30] = &b;
But it's unlikely to be what you want, as other people have commented. You probably need to clarify your underlying goal - people can only speculate otherwise.
Just to follow on from MooingDuck's remark, I can in fact see a way to do it without the typedef, but not directly:
template <typename T>
T *create(T *const &)
{
return new T;
}
int (**a)[30] = create(a);
It's not pretty though.
What do you expect to get by writing &(&var)? This is an equivalent of address of address of a block of memory. Doing things like this just to satisfy the number of * in your code makes no sense.
Think about it - how can you get an address of an address? Even if, by some sheer luck or weird language tricks you manage to do it, there no way it will work.
i am stuck and unable to figure out why this is the following piece of code is not running .I am fairly new to c/c++.
#include <iostream>
int main(){
const char *arr="Hello";
const char * arr1="World";
char **arr2=NULL;
arr2[0]=arr;
arr2[1]=arr1;
for (int i=0;i<=1;i++){
std::cout<<arr2[i]<<std::endl;
}
return 0;
}
where as this is running perfectly fine
#include <iostream>
int main(){
const char *arr="Hello";
const char * arr1="World";
char *arr2[1];
arr2[0]=arr;
arr2[1]=arr1;
for (int i=0;i<=1;i++){
std::cout<<arr2[i]<<std::endl;
}
return 0;
}
Why is this? and generally how to iterate over a char **?
Thank You
char *arr2[1]; is an array with one element (allocated on the stack) of type "pointer to char". arr2[0] is the first element in that array. arr2[1] is undefined.
char **arr2=NULL; is a pointer to "pointer to char". Note that no memory is allocated on the stack. arr2[0] is undefined.
Bottom line, neither of your versions is correct. That the second variant is "running perfectly fine" is just a reminder that buggy code can appear to run correctly, until negligent programming really bites you later on and makes you waste hours and days in debugging because you trashed the stack.
Edit: Further "offenses" in the code:
String literals are of type char const *, and don't you forget the const.
It is common (and recommended) practice to indent the code of a function.
It is (IMHO) good practice to add spaces in various places to increase readability (e.g. post (, pre ), pre and post binary operators, post ; in the for statement etc.). Tastes differ, and there is a vocal faction that actually encourages leaving out spaces wherever possible, but you didn't even do that consistently - and consistency is universially recommended. Try code reformatters like astyle and see what they can do for readability.
This is not correct because arr2 does not point to anything:
char **arr2=NULL;
arr2[0]=arr;
arr2[1]=arr1;
correct way:
char *arr2[2] = { NULL };
arr2[0]=arr;
arr2[1]=arr1;
This is also wrong, arr2 has size 1:
char *arr2[1];
arr2[0]=arr;
arr2[1]=arr1;
correct way is the same:
char *arr2[2] = { NULL };
arr2[0]=arr;
arr2[1]=arr1;
char **arr2=NULL;
Is a pointer to a pointer that points to NULL while
char *arr2[1];
is an array of pointers with already allocated space for two items.
In the second case of the pointer to a pointer you are are trying to write data in a memory location that does not exist while in the first place the compiler has already allocated two slots of memory for the array so you can assign values to the two elements.
If you think of it very simplistically, a C pointer is nothing but an integer variable, whose value is actually a memory address. So by defining char *x = NULL you are actually defining a integer variable with value NULL (i.e zero). Now suppose you write something like *x = 5; This means go to the memory address that is stored inside x (NULL) and write 5 in it. Since there is no memory slot with address 0, the the entire statement fails.
To be honest it;s been ages since I last had to deal with such stuff however this little tutorial here, might clear the motions of array and pointers in C++.
Put simply the declaration of a pointer does NOT reserve any memory, where as the declration of a array doesn't.
In your first example
Your line char **arr2=NULL declares a pointer to a pointer of characters but does not set it to any value - thus it is initiated pointing to the zero byte (NULL==0). When you say arr2[0]=something you are attempting to place a valuei nthis zero location which does not belong to you - thus the crash.
In your second example:
The declaration *arr2[2] does reserve space for two pointers and thus it works.
I have a struc like this:
struct process {int PID;int myMemory[];};
however, when I try to use it
process p;
int memory[2];
p.myMemory = memory;
I get an criptic error from eclipse saying int[0] is not compatible with int[2];
what am i doing wrong?
Thanks!
Don't use static arrays, malloc, or even new if you're using C++. Use std::vector which will ensure correct memory management.
#include <vector>
struct Process {
int pid;
std::vector<int> myMemory;
};
Process p;
p.reserve(2); // allocates enough space on the heap to store 2 ints
p.myMemory.push_back( 4815 ); // add an index-zero element of 4815
p.myMemory.push_back( 162342 ); // add an index-one element of 162342
I might also suggest creating a constructor so that pid does not initially have an undefined value:
struct Process {
Process() : pid(-1), myMemory() {
}
int pid;
std::vector<int> myMemory;
};
I think you should declare myMemory as an int* then malloc() when you know the size of it. After this it can be used like a normal array. Int[0] seems to mean "array with no dimension specified".
EXAMPLE:
int *a; // suppose you'd like to have an array with user specified length
// get dimension (int d)
a = (int *) malloc(d * sizeof(int));
// now you can forget a is a pointer:
a[0] = 5;
a[2] = 1;
free((void *) a); // don't forget this!
All these answers about vector or whatever are confused :) using a dynamically allocated pointer opens up a memory management problem, using vector opens up a performance problem as well as making the data type a non-POD and also preventing memcpy() working.
The right answer is to use
Array<int,2>
where Array is a template the C++ committee didn't bother to put in C++99 but which is in C++0x (although I'm not sure of the name). This is an inline (no memory management or performance issues) first class array which is a wrapper around a C array. I guess Boost has something already.
In C++, array definition is almost equal to pointer constants, meaning that their address cannot be changed, while the values which they point to can be changed. That said, you cannot copy elements of an array into another by the assignment operator. You have to go through the arrays and copy the elements one by one and check for the boundary conditions yourself.
The syntax ...
struct process {int PID;int myMemory[];};
... is not valid C++, but it may be accepted by some compilers as a language extension. In particular, as I recall g++ accepts it. It's in support for the C "struct hack", which is unnecessary in C++.
In C++, if you want a variable length array in a struct, use std::vector or some other array-like class, like
#include <vector>
struct Process
{
int pid;
std::vector<int> memory;
};
By the way, it's a good idea to reserve use of UPPERCASE IDENTIFIERS for macros, so as to reduce the probability of name collisions with macros, and not make people reading the code deaf (it's shouting).
Cheers & hth.,
You cannot make the array (defined using []) to point to another array. Because the array identifier is a const pointer. You can change the value pointed by the pointer but you cannot change the pointer itself. Think of "int array[]" as "int* const array".
The only time you can do that is during initialization.
// OK
int array[] = {1, 2, 3};
// NOT OK
int array[];
array = [1, 2, 3]; // this is no good.
int x[] is normally understood as int * x.
In this case, it is not, so if you want a vector of integers of an undetermined number of positions, change your declaration to:
struct process {int PID;int * myMemory;};
You should change your initialization to:
int memory[2];
p.myMemory = new int[ 10 ];
How does a pointer points to [-1]th index of the array produce legal output everytime. What is actually happening in the pointer assignment?
#include<stdio.h>
int main()
{
int realarray[10];
int *array = &realarray[-1];
printf("%p\n", (void *)array);
return 0;
}
Code output:
manav#workstation:~/knr$ gcc -Wall -pedantic ptr.c
manav#workstation:~/knr$ ./a.out
0xbf841140
EDIT: If this scenario is valid, then can i use this to define an array whose index start from 1 instead of 0, namely: array[1], array[2],...
Youre simply getting a pointer that contains the address of that "imaginary" location, i.e. the location of the first element &realarray[0] minus the size of one element.
This is undefined behavior, and might break horribly if, for instance, your machine has a segmented memory architecture. It's working because the compiler writer has chosen to implement the arithmetic as outlined above; that could change at any moment, and another compiler might behave totally differently.
a[b] is defined as *(a+b)
therefore a[-1] is *(a-1)
Whether a-1 is a valid pointer and therefore the dereference is valid depends on the context the code is used in.
The behaviour is undefined.
What you have observed may have happened in your particular compiler and configuration, but anything may happen in a different situation. You cannot rely on this behaviour at all.
The behavior is undefined. You can only calculate a pointer to any of the elements of an array, or one past, but that's it. You can only dereference a pointer to any of the elements of an array (not the one past pointer). Looking at your variable names, looks like you're asking a question from this C FAQ. I think that the answer on the FAQ is very good.
Although, as others have noted, it is undefined behaviour in this case, it compiles without warnings because in general, foo[-1] might be valid.
For example, this is fine:
int realarray[10] = { 10, 20, 30, 40 };
int *array = &realarray[2];
printf("%d\n", array[-1]);
In C and C++, array indexes are not checked at runtime. You are performing pointer arithmetic which may or may not end up giving defined results (not here).
However, in C++ you can use an array class that does provide bounds checks, e.g boost::array or std::tr1::array (to be added to standard library in C++0x):
#include <cstdio>
#include <boost/array.hpp>
int main()
{
try {
boost::array<int, 10> realarray;
int* p = &realarray.at(-1);
printf("%p\n", (void *)p);
} catch (const std::exception& e) {
puts(e.what());
}
}
Output:
array<>: index out of range
Also produces a compiler warning:
8 test.cpp [Warning] passing negative
value -0x000000001' for converting 1
ofT& boost::array::at(size_t)
[with T = int, unsigned int N = 10u]'
It simply points to the address of the item just ahead of the array in memory.
The array can simply be thought of as being a pointer. This is then simply decremented by one.
Here you just performing the pointer arithmetic , It will get firs index address of the relarray
See, if you &relarray[+1] , you would get the second element address of the array. since
&relarray[0] is pointing the first index address.
array points to one location before the starting address of realarray. However, what confused me is why does this compiled without any warnings.
You're just pointing to the 4 bytes located before the array.
This is perfectly well defined. Your code is guaranteed to be accepted by all compilers, and never crash at run time. C/C++ pointers are a numeric data type that obey the rules of arithmetic. Addition and subtraction work, and the bracket notation [] is just a fancy syntax for addition. NULL is literally the integer 0.
And this is why C/C++ are dangerous. The compiler will let you create pointers that point anywhere without complaint. Dereferencing the wild pointer in your example, *array = 1234; would produce undefined behavior, anything from subtle corruption to a crash.
Yes, you could use it to index from 1. Don't do this! The C/C++ idiom is to always index from 0. Other people who saw the code indexing from 1 would be tempted to "fix" it to index from 0.
The experiment could have provided little more clue if it was the following. Instead of printing the pointer value as
printf("%p\n", (void *)array);
, print the array element value
printf("%d\n", *array);
Thats because printing a pointer with %p will always produce some output (without any misbehavior), but nothing can be deduced from it.
I'm not sure if the term's actually "Array Addition".
I'm trying to understand what does the following line do:
int var[2 + 1] = {2, 1};
How is that different from int var[3]?
I've been using Java for several years, so I'd appreciate if explained using Java-friendly words.
Edit: Thousands of thanks to everyone who helped me out, Occam's Razor applies here.
It's not different. C++ allows expressions (even non-constant expressions) in the subscripts of array declarations (with some limitations; anything other than the initial subscript on a multi-dimensional array must be constant).
int var[]; // illegal
int var[] = {2,1}; // automatically sized to 2
int var[3] = {2,1}; // equivalent to {2,1,0}: anything not specified is zero
int var[3]; // however, with no initializer, nothing is initialized to zero
Perhaps the code you are reading writes 2 + 1 instead of 3 as a reminder that a trailing 0 is intentional.
It is any different from int var[3]. The compiler will evaluate 2 + 1 and replace it with 3 during compilation.
How is that different from int var[3]?
In no way that I can see.
It isn't any different; it is int var[3].
Someone might write their array like this when writing char arrays in order to add space for the terminating 0.
char four[4 + 1] = "1234";
It doesn't seem to make any sense working with an int array.
var[2 + 1] is not different from var[3]. The author probably wanted to emphasize that var array will hold 2 data items and a terminating zero.
This creates an array of 3 integers. You're right, there is no difference whether you express it as2 + 1 or 3, as long as the value is compile-time constant.
The right side of the = is an initializer list and it tells the compiler how to fill the array. The first value is 2, the second 1 and the third is 0 since no more values are specified.
The zero fill only happens when you use an initializer list. Otherwise there is no guarantee of that the array has any particular values.
I've seen this done with char arrays, to emphasize that one char is reserved for a string terminator, but never for an int array.