LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 08-19-2015, 09:20 PM   #1
flatang
LQ Newbie
 
Registered: Feb 2015
Location: Dublin
Distribution: whats a distro?
Posts: 1

Rep: Reputation: Disabled
pointers and multidimensional arrays in C


I was following a tutorial and got lost when my program wouldn't compile and it is exactly the same as the working program in the tutorial..

#include <stdio.h>
#include <stdbool.h>

int main() {

int array[3][4]= {1,2,3,4,5,6,7,8,9,10,11,12};

int *aPtr = &array;

for(;aPtr < array+4; aPtr++ )
{
printf("%d\n ", *aPtr);
}
return 0;
}

I gets a compile error that says the following:

warning: initialization from incompatible pointer type [enabled by default]

for the line : int *aPtr = &array;

I'm using gedit and no make file just gcc -o..

the program in the tutorial builds for the guy just fine.
do I need a header file??
 
Old 08-20-2015, 04:53 AM   #2
wildwizard
Member
 
Registered: Apr 2009
Location: Oz
Distribution: slackware64-14.0
Posts: 875

Rep: Reputation: 282Reputation: 282Reputation: 282
Quote:
Originally Posted by flatang View Post
for the line : int *aPtr = &array;
Should be (for gcc's annoying parser)
int *aPtr = &array[0][0];

Further EDIT

GCC also hates your for loop
Code:
for(;aPtr < array+4; aPtr++ )
Can make it happy by casting
Code:
for(;aPtr < (int *)array+4; aPtr++ )
GCC is pretty hard core on standards and a lot of old C tutorials will run afoul of the parser.

Last edited by wildwizard; 08-20-2015 at 05:11 AM.
 
1 members found this post helpful.
Old 08-20-2015, 06:17 AM   #3
Peverel
Member
 
Registered: May 2009
Location: Chelmsford, England
Distribution: OpenSuse 12.2 and 13.2, Leap 4.2
Posts: 128

Rep: Reputation: 24
Actually, the parser is doing its job! The point is that array is actually of type int*, that is, it is a pointer to the first element of the array. &array is a pointer to the location that contains the array pointer, and is therefore superfluous (and wrong).

int *aPtr = array

should work.

Last edited by Peverel; 08-20-2015 at 06:18 AM.
 
Old 08-20-2015, 03:27 PM   #4
darkonc
LQ Newbie
 
Registered: Nov 2009
Posts: 11

Rep: Reputation: 1
Quote:
Originally Posted by flatang View Post
I was following a tutorial and got lost when my program wouldn't compile and it is exactly the same as the working program in the tutorial..

the program in the tutorial builds for the guy just fine.
do I need a header file??
Note that those are simply warnings -- not errors. Just letting you know that you're doing kinda weird stuff.

C multidimensional arrays are essentially arrays of arrays (if that makes sense to you). and a single-dimensional array is treated much like a simple pointer.

As a result, gcc will also happily let you get away with array[0], instead of (int*)array, or &array[0][0]
 
Old 08-20-2015, 04:25 PM   #5
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,877
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
I agree with the two style recommendations of:
Code:
int *aPtr = &array[0][0];
int *aPtr = array;
Both are equivalent.

Cautionary note: Be aware of how the pointer moves and what is considered to be a row versus a column in that two dimensional array. Further, another thing you could have, and should have done would be:
Code:
int array[3][4]= {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
Note also that my interpretation is that the loop code, while legal syntax is bounding the limit test on the start pointer of the array, plus 4 integers beyond that start. In short, "pointing at 5". aPtr++ moves the pointer up by one integer at a time. array+4 is base address of array, plus either an offset of 4 integers, 4 array entries, or 4 sub-array entries. I'd have to run and detail the addresses as the pointer progressed to know correctly.

I shan't do it, I'll let you the OP debug as you see fit. You could use gdb and step through it and examine the pointer value as the loop progresses.

Just cautionary. I tend to not use stuff that's "tricky" which I don't understand. Sorry, that sounds bad, like me saying 'code I don't understand is tricky and hence I avoid it' but ... well that's a harsh truth in my world. Make sure "you" understand it if you intend to use it as part of your regular coding efforts.
 
1 members found this post helpful.
Old 08-20-2015, 05:53 PM   #6
wildwizard
Member
 
Registered: Apr 2009
Location: Oz
Distribution: slackware64-14.0
Posts: 875

Rep: Reputation: 282Reputation: 282Reputation: 282
Quote:
Originally Posted by rtmistler View Post
I agree with the two style recommendations of:
Code:
int *aPtr = array;
Both are equivalent.
I tested that one and GCC hated it as well, which is why I mentioned GCC's over the top parser as been annoying.

I should point out that according to an ANSI C book I have here that that method is perfectly legal so I have no idea why GCC is complaining about it.

GCC 4.8.2 used for testing (including the old -ansi switch)
 
Old 08-21-2015, 05:37 AM   #7
millgates
Member
 
Registered: Feb 2009
Location: 192.168.x.x
Distribution: Slackware
Posts: 852

Rep: Reputation: 389Reputation: 389Reputation: 389Reputation: 389
Quote:
Originally Posted by wildwizard View Post
I tested that one and GCC hated it as well, which is why I mentioned GCC's over the top parser as been annoying.

I should point out that according to an ANSI C book I have here that that method is perfectly legal so I have no idea why GCC is complaining about it.

GCC 4.8.2 used for testing (including the old -ansi switch)
gcc is not complaining about that one. That one is actually correct. Please note the difference between that and the syntax actually used in the original post:

Code:
int *aPtr = &array; /* incorrect */
int *aPtr = array;  /* correct   */
gcc is not "hard core". Conforming to standards is a good thing. It helps you write good code.
 
Old 08-21-2015, 06:47 AM   #8
rtmistler
Moderator
 
Registered: Mar 2011
Location: USA
Distribution: MINT Debian, Angstrom, SUSE, Ubuntu, Debian
Posts: 9,877
Blog Entries: 13

Rep: Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930Reputation: 4930
I usually keep an example Makefile copy around so that I can re-use flags. There are more, but these tend to work very well for me:
Code:
CFLAGS= -I. -O0 -ggdb -Wformat=2 -Werror -Wall -Wextra -Wswitch-default -Wswitch
-enum -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wmissing-
noreturn
And you edit the -0 based on your preferences at the time and whether or not you wish optimization.
 
1 members found this post helpful.
Old 08-21-2015, 10:27 AM   #9
DarrenDrapkin
Member
 
Registered: Aug 2014
Location: Leeds, England
Distribution: Slackware x86 64 version 15.0
Posts: 127
Blog Entries: 3

Rep: Reputation: 27
Quote:
int *aPtr = &array;

for(;aPtr < array+4; aPtr++ )
This bit could be summarised as follows, to look more conventional. It also shows that only the first 4 elements of 'array' are to be operated on.
Code:
 int *aPtr;
for(aPtr=array;aPtr < array+4; aPtr++ )
 
Old 08-21-2015, 06:00 PM   #10
wildwizard
Member
 
Registered: Apr 2009
Location: Oz
Distribution: slackware64-14.0
Posts: 875

Rep: Reputation: 282Reputation: 282Reputation: 282
Quote:
Originally Posted by millgates View Post
gcc is not complaining about that one. That one is actually correct. Please note the difference between that and the syntax actually used in the original post:

Code:
int *aPtr = &array; /* incorrect */
int *aPtr = array;  /* correct   */
gcc is not "hard core". Conforming to standards is a good thing. It helps you write good code.
Code:
tmp.c: in function 'main':
tmp.c:11:16: warning: initialization from incompatible pointer type [enabled by default]
int *aPtr = array;
            ^
I suggest you actually try GCC and not talk theory, because I have and it is complaining about that.
 
1 members found this post helpful.
Old 08-22-2015, 12:18 PM   #11
darkonc
LQ Newbie
 
Registered: Nov 2009
Posts: 11

Rep: Reputation: 1
Exclamation Don't ever use that code in a real program

Quote:
Originally Posted by rtmistler View Post
Cautionary note: Be aware of how the pointer moves and what is considered to be a row versus a column in that two dimensional array.
.....
I'd have to run and detail the addresses as the pointer progressed to know correctly.
The example code is great for showing the equivalences between pointers and array -- but I don't consider it to be either portable, nor particularly easy to understand. I can think of at least two different 'reasonable' results for that code; I'd have to (carefully) read that portion of "The 'C' Programming Language" to figure out which was the 'proper' way of doing things; and I wouldn't bet my life that some implementations wouldn't do it 'the other way'.


In short: If I saw those constructs in live code, I'd hunt down the responsible programmer with a paintball gun.


a much more sane way of doing the loop:
int i;

for(i=0; i<4; i++)
{
printf("%d\n ", aPtr[i] );
}

Or, (if you actually wanted to change aPtr as a side effect:
for(i=0; i<4; i++)
{
printf("%d\n ", *aPtr++ );
}
 
Old 08-22-2015, 02:08 PM   #12
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,774

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Code:
int array[3][4]= {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

int *aPtr = &array; /* incorrect */
int *aPtr = array;  /* incorrect */

int *aPtr = array[0]; /* correct */
int *aPtr = &array[0][0]; /* correct */

// similarly:

    for(;aPtr < array+4; aPtr++ ) /* incorrect */
    for(;aPtr < array[4]; aPtr++ ) /* incorrect (because it goes past end of array) */
    for(;aPtr < array[3]; aPtr++ ) /* correct */
    for(;aPtr < &array[3][0]; aPtr++ ) /* correct */
    for(;aPtr < &array[2][4]; aPtr++ ) /* correct */
Quote:
Originally Posted by wildwizard
I should point out that according to an ANSI C book I have here that that method is perfectly legal so I have no idea why GCC is complaining about it.
Due to array decay,
the expression array is equivalent to &array[0]. Since
array is 3 arrays of arrays of 4 ints, array[0] is an array of
4 ints, so &array[0] is a pointer to an array of 4 ints rather than a
pointer an int.

Last edited by ntubski; 08-24-2015 at 10:47 AM. Reason: add definition of array variable
 
2 members found this post helpful.
Old 08-23-2015, 06:18 AM   #13
DarrenDrapkin
Member
 
Registered: Aug 2014
Location: Leeds, England
Distribution: Slackware x86 64 version 15.0
Posts: 127
Blog Entries: 3

Rep: Reputation: 27
Quote:
Originally Posted by wildwizard View Post
Code:
tmp.c: in function 'main':
tmp.c:11:16: warning: initialization from incompatible pointer type [enabled by default]
int *aPtr = array;
            ^
I suggest you actually try GCC and not talk theory, because I have and it is complaining about that.
Thank you, It is some months since I last wrote something in C. I have been re-learning APL, and it does array handling internally.
 
Old 08-24-2015, 10:31 AM   #14
darkonc
LQ Newbie
 
Registered: Nov 2009
Posts: 11

Rep: Reputation: 1
Quote:
Originally Posted by ntubski View Post
Code:
int *aPtr = &array; /* incorrect */
int *aPtr = array;  /* incorrect */

int *aPtr = array[0]; /* correct */
int *aPtr = &array[0][0]; /* correct */
Arrays and pointers in C are (somewhat) intechangable.
All of the above are legal -- but I would describe the first three as variable degrees of silly and stupid, because it's not very clear exactly what you're trying to do.
The first one is especially problematic because it is context dependant.
Since (in this case) array is a 'real' array, &array will return the address of the array.
However, if it were a passed-in variable, it would be implemented as a pointer, and &array would/should returrn the address of the pointer (possibly depending on the pedantic correctness of the implementation)

Because that construct is context and/or implementation dependant, I would declare it to be especially stupid.
 
Old 08-24-2015, 10:53 AM   #15
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian, Arch
Posts: 3,774

Rep: Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081Reputation: 2081
Quote:
Originally Posted by darkonc View Post
The first one is especially problematic because it is context dependant.
Yeah, I meant all those statements specifically in the case where array has type int[3][4], I've now edited that in.

Quote:
However, if it were a passed-in variable, it would be implemented as a pointer, and &array would/should returrn the address of the pointer (possibly depending on the pedantic correctness of the implementation)
Indeed, this show that arrays and pointers are not interchangeable.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
clarification of pointers to multidimensional arrays atlantis43 Programming 16 10-08-2013 09:04 AM
Multidimensional pointers in C rubadub Programming 4 03-26-2008 07:47 AM
Question about outputing arrays with pointers, then just arrays... RHLinuxGUY Programming 1 04-12-2006 05:40 AM
resizing multidimensional arrays in C++ banerji Programming 2 07-12-2004 07:27 PM
help w/ pointers vs arrays PTBmilo Programming 3 04-10-2003 05:13 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 09:19 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration