473,549 Members | 2,615 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Some doubts on variable-length array

Hello experts,

I have seen following the code snippet given by Marc Boyer (with slight
changes by me for a better format), and have doubts on it. I am so
grateful if you can give me your kindly help and hints on this problem.

1. Does the function call `foo(3, 3, tab);' refer to the data outside
the array `int tab[9];'. The available subscription for a 3X3 2-D array
should be 0..2 X 0..2, I think.

2. For the available function call `foo(2, 2, tab);' (I do not think
the second one is unavailable, just not sure.), which element in the
array `int tab[9];' does tab[0][0] refer to inside the body of the
function `foo'. I want to know the exact one int the format `tab[0] ..
tab [8]'.

And which element in `int tab[9];' does tab[1][1] refer to.

I can not figure it out for some while on it. The GCC4.1 says it does
not support the variable-length array of C99, but I can compile this
program on even GCC3.3.5, and also on GCC4.1 after I installed this
newest one. I also get the same result of the program as Marc Boyer.

Sincerely,

lovecreatesbeau ty

/* sample by Marc Boyer */

#include <stdio.h>

void
foo(int size_x, int size_y, int tab[size_x][size_y])
{
printf("tab[1][1] == %d\n", tab[1][1]);
}

int
main()
{
int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
foo(2, 2, tab);
foo(3, 3, tab);

return 0;
}

news> ./a.out
tab[1][1] == 3
tab[1][1] == 4

Mar 31 '06 #1
8 1773
I can understand the behaviour of these statements marked `/* A. don't
understand */' in following code, but do not understand the statements
marked `/* B. understand */' .

The behaviour of the following statements of A kind is different to B
kind.

Thank you.

#include <stdio.h>

void foo(int size_x, int size_y, int tab[size_x][size_y])
{
printf("tab[1][1] == %d\n", tab[1][1]);
}

int main()
{
/* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
int tab[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};

foo(2, 2, tab); /* A. don't understand */
printf("%i\n", tab[2][2]); /* B. understand */
printf("%i\n", *(*(tab+2)+2)); /* B. understand */
printf("\n\n");

foo(3, 3, tab); /* A. don't understand */
printf("%i\n", tab[3][3]); /* B. understand */
printf("%i\n", *(*(tab+3)+3)); /* B. understand */
printf("\n\n");

return 0;
}

Mar 31 '06 #2

"lovecreatesbea uty" <lo************ ***@gmail.com> wrote in message
news:11******** *************@i 39g2000cwa.goog legroups.com...
I can understand the behaviour of these statements marked `/* A. don't
understand */' in following code, but do not understand the statements
marked `/* B. understand */' .

The behaviour of the following statements of A kind is different to B
kind.

Thank you.

#include <stdio.h>

void foo(int size_x, int size_y, int tab[size_x][size_y]) Here foo is being told that tab is an array with dimensions
[size_x][size_y].
It will assume that this is actually the case, regardless of the true size
of the array passed to it in the calling function. {
printf("tab[1][1] == %d\n", tab[1][1]);
}
if this were void foo( int **tab),
foo would not know the rank of the array

int main()
{
/* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
int tab[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};

foo(2, 2, tab); /* A. don't understand */ Call function foo, and tell foo that tab is a 2x2 array
printf("%i\n", tab[2][2]); /* B. understand */
printf("%i\n", *(*(tab+2)+2)); /* B. understand */
printf("\n\n");

foo(3, 3, tab); /* A. don't understand */ Call function foo, and tell foo that tab is a 3x3 array
printf("%i\n", tab[3][3]); /* B. understand */ Error - index out of bounds printf("%i\n", *(*(tab+3)+3)); /* B. understand */ Error - index out of bounds printf("\n\n");

return 0;
}

--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Mar 31 '06 #3
On Fri, 31 Mar 2006 02:00:45 -0800, lovecreatesbeau ty wrote:
I can understand the behaviour of these statements marked `/* A. don't
understand */' in following code, but do not understand the statements
marked `/* B. understand */' .
Did you mean it that way round? I've commented on both just in case.
#include <stdio.h>

void foo(int size_x, int size_y, int tab[size_x][size_y])
{
printf("tab[1][1] == %d\n", tab[1][1]);
prints the 2nd element of the 2nd element of tab.
}

int main()
{
/* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
int tab[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
My compiler (gcc 4.0.1) warns me I should write:

int tab[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};

although it accepts the flat list as well.
foo(2, 2, tab); /* A. don't understand */
This calls "lies" to foo telling it that the array is 2x2 so foo sees it
as if it were "int tab[2][2] = {{0, 1}, {2, 3}};". Element [1][1] is 3
and this is what is printed.
printf("%i\n", tab[2][2]); /* B. understand */
The declaration of tab is in scope here so there should be no confusion.
The third element of the third element of tab is 8.
printf("%i\n", *(*(tab+2)+2)); /* B. understand */
This is another way to write the same thing. The array name tab is
treated as a pointer to its first element (an array of three ints).
Adding 2 to this pointer (tab + 2) moves it by two "strides" to make a
pointer that points to the third element (another array of three ints).
*(tab + 2) is this array, but again, the array is treated as a pointer to
its first element (an int). Adding 2 to that gives a pointer that points
to the number 8. The final * de-references that pointer to give the value
8.
printf("\n\n");

foo(3, 3, tab); /* A. don't understand */
This call does not "lie". So inside foo it is seen as it was defined and
element [1][1] is the number 4.
printf("%i\n", tab[3][3]); /* B. understand */
printf("%i\n", *(*(tab+3)+3)); /* B. understand */
These two are exactly as above, but the array is being index out of bounds
so you get undefined behaviour (probably a segmentation fault, or maybe
just garbage being printed).
printf("\n\n");

return 0;
}


--
Ben.
Mar 31 '06 #4

Ben Bacarisse wrote:
foo(2, 2, tab); /* A. don't understand */


This calls "lies" to foo telling it that the array is 2x2 so foo sees it
as if it were "int tab[2][2] = {{0, 1}, {2, 3}};". Element [1][1] is 3
and this is what is printed.


I know it before that functions regard an array argument same as a
pointer. So how can the layout/dimension of an actual array argument be
known inside the function body? Are new meanings/semantics given to
array arguments when they are variable-length array?
foo(3, 3, tab); /* A. don't understand */


This call does not "lie". So inside foo it is seen as it was defined and
element [1][1] is the number 4.


The original array is: /* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
, if it is used instead, then foo(3, 3, tab); lies again, right?

I can understand the original sample code in your way, but get more
anxious on how a function knows the layout/dimension of actual array
arguments.

Mar 31 '06 #5
On Fri, 31 Mar 2006 09:12:25 -0800, lovecreatesbeau ty wrote:

Ben Bacarisse wrote:
> foo(2, 2, tab); /* A. don't understand */
This calls "lies" to foo telling it that the array is 2x2 so foo sees it
as if it were "int tab[2][2] = {{0, 1}, {2, 3}};". Element [1][1] is 3
and this is what is printed.


I know it before that functions regard an array argument same as a
pointer. So how can the layout/dimension of an actual array argument be
known inside the function body? Are new meanings/semantics given to
array arguments when they are variable-length array?


Yes. The special syntax of these arguments lets the compiler know how big
each row of the parameter array is.
> foo(3, 3, tab); /* A. don't understand */


This call does not "lie". So inside foo it is seen as it was defined and
element [1][1] is the number 4.


The original array is: /* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
, if it is used instead, then foo(3, 3, tab); lies again, right?


Yes and this is a bigger lie. But I put "lie" in quotes, because it may
be OK to do it. Telling a function the "shape" of the data array is fine
so long as you know what will happen when you do that.

If you want to treat a flat array as a collection of rows, then you are
free to do so but you will need to persuade the compiler with a cast in
the call to foo: foo(3, 3, (int (*)[3])tab) and you will not be able to
write tab[2][2] within scope of the flat definition. Nor will the mess
with all the pointer arithmetic work. In short, you need a very good
reason to go messing about like that. If you have 2D array, then just
declare it and use it. Pass at least the "row size" to any functions that
use the array and all will be fine. Passing both sizes makes sense for
many applications and helps to document the code.
--
Ben.
Mar 31 '06 #6

Ben Bacarisse wrote:
On Fri, 31 Mar 2006 09:12:25 -0800, lovecreatesbeau ty wrote:

Ben Bacarisse wrote:
> foo(2, 2, tab); /* A. don't understand */

This calls "lies" to foo telling it that the array is 2x2 so foo sees it
as if it were "int tab[2][2] = {{0, 1}, {2, 3}};". Element [1][1] is 3
and this is what is printed.


I know it before that functions regard an array argument same as a
pointer. So how can the layout/dimension of an actual array argument be
known inside the function body? Are new meanings/semantics given to
array arguments when they are variable-length array?


Yes. The special syntax of these arguments lets the compiler know how big
each row of the parameter array is.
> foo(3, 3, tab); /* A. don't understand */

This call does not "lie". So inside foo it is seen as it was defined and
element [1][1] is the number 4.


The original array is: /* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
, if it is used instead, then foo(3, 3, tab); lies again, right?


Yes and this is a bigger lie. But I put "lie" in quotes, because it may
be OK to do it. Telling a function the "shape" of the data array is fine
so long as you know what will happen when you do that.

If you want to treat a flat array as a collection of rows, then you are
free to do so but you will need to persuade the compiler with a cast in
the call to foo: foo(3, 3, (int (*)[3])tab) and you will not be able to
write tab[2][2] within scope of the flat definition. Nor will the mess
with all the pointer arithmetic work. In short, you need a very good
reason to go messing about like that. If you have 2D array, then just
declare it and use it. Pass at least the "row size" to any functions that
use the array and all will be fine. Passing both sizes makes sense for
many applications and helps to document the code.
--
Ben.


Thank you.

How is it going whan I add `foo(0, 0, tab)' and `foo(1, 1, tab)' in the
code snippet as following?

Can I think each function call refers to the array element as following
(I get inspired on it form another people goodluckyxl):

foo(0, 0, tab) refers to: tab[1+sizeof(int[0])/sizeof(int)] or
tab[1+0/sizeof(int)]

foo(0, 0, tab) refers to: tab[1+sizeof(int[1])/sizeof(int)]

foo(0, 0, tab) refers to: tab[1+sizeof(int[2])/sizeof(int)]

foo(0, 0, tab) refers to: tab[1+sizeof(int[3])/sizeof(int)]

#include <stdio.h>

void
foo(int size_x, int size_y, int tab[size_x][size_y])
{
printf("tab[1][1] == %d\n", tab[1][1]);
}

int
main()
{
int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};

foo(0, 0, (int(*)[0])tab); /* foo(0, 0, tab); */
foo(1, 1, (int(*)[1])tab); /* foo(1, 1, tab); */

foo(2, 2, (int(*)[2])tab);
foo(3, 3, (int(*)[3])tab);

return 0;
}

Apr 1 '06 #7

Ben Bacarisse wrote:
On Fri, 31 Mar 2006 09:12:25 -0800, lovecreatesbeau ty wrote:

Ben Bacarisse wrote:
> foo(2, 2, tab); /* A. don't understand */

This calls "lies" to foo telling it that the array is 2x2 so foo sees it
as if it were "int tab[2][2] = {{0, 1}, {2, 3}};". Element [1][1] is 3
and this is what is printed.


I know it before that functions regard an array argument same as a
pointer. So how can the layout/dimension of an actual array argument be
known inside the function body? Are new meanings/semantics given to
array arguments when they are variable-length array?


Yes. The special syntax of these arguments lets the compiler know how big
each row of the parameter array is.
> foo(3, 3, tab); /* A. don't understand */

This call does not "lie". So inside foo it is seen as it was defined and
element [1][1] is the number 4.


The original array is: /* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
, if it is used instead, then foo(3, 3, tab); lies again, right?


Yes and this is a bigger lie. But I put "lie" in quotes, because it may
be OK to do it. Telling a function the "shape" of the data array is fine
so long as you know what will happen when you do that.

If you want to treat a flat array as a collection of rows, then you are
free to do so but you will need to persuade the compiler with a cast in
the call to foo: foo(3, 3, (int (*)[3])tab) and you will not be able to
write tab[2][2] within scope of the flat definition. Nor will the mess
with all the pointer arithmetic work. In short, you need a very good
reason to go messing about like that. If you have 2D array, then just
declare it and use it. Pass at least the "row size" to any functions that
use the array and all will be fine. Passing both sizes makes sense for
many applications and helps to document the code.
--
Ben.


Thank you.

How is it going whan I add `foo(0, 0, tab)' and `foo(1, 1, tab)' in the
code snippet as following?

Can I think each function call refers to the array element as following
(I get inspired on it form another people goodluckyxl): (sorry to make
mistakes on following descriptions in my previous post)

foo(0, 0, tab) refers to: tab[1+sizeof(int[0])/sizeof(int)] or
tab[1+0/sizeof(int)]

foo(1, 1, tab) refers to: tab[1+sizeof(int[1])/sizeof(int)]

foo(2, 2, tab) refers to: tab[1+sizeof(int[2])/sizeof(int)]

foo(3, 3, tab) refers to: tab[1+sizeof(int[3])/sizeof(int)]

#include <stdio.h>

void
foo(int size_x, int size_y, int tab[size_x][size_y])
{
printf("tab[1][1] == %d\n", tab[1][1]);
}

int
main()
{
int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8};

foo(0, 0, (int(*)[0])tab); /* foo(0, 0, tab); */
foo(1, 1, (int(*)[1])tab); /* foo(1, 1, tab); */

foo(2, 2, (int(*)[2])tab);
foo(3, 3, (int(*)[3])tab);

return 0;
}

Apr 1 '06 #8
"Ben Bacarisse" <be********@bsb .me.uk> wrote in message
news:pa******** *************** *****@bsb.me.uk ...
On Fri, 31 Mar 2006 02:00:45 -0800, lovecreatesbeau ty wrote:
#include <stdio.h>

void foo(int size_x, int size_y, int tab[size_x][size_y])
{
printf("tab[1][1] == %d\n", tab[1][1]);


prints the 2nd element of the 2nd element of tab.
}

int main()
{
/* int tab[9] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; */
int tab[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};


My compiler (gcc 4.0.1) warns me I should write:

int tab[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};

although it accepts the flat list as well.
foo(2, 2, tab); /* A. don't understand */


This calls "lies" to foo telling it that the array is 2x2 so foo sees it
as if it were "int tab[2][2] = {{0, 1}, {2, 3}};". Element [1][1] is 3
and this is what is printed.


This lie makes my compiler produce a warning. That is reasonable because the
types are incompatible. So that makes me wonder: is this guaranteed to work;
always produce the same result? I would think yes but i would like someone
to confirm it.
Apr 2 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
1509
by: abbas reji | last post by:
--0-599929911-1059996886=:4358 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit Content-Id: Content-Disposition: inline ________________________________________________________________________
1
1486
by: Piotre Ugrumov | last post by:
I have some problems and some doubts. I have implemented a class hierachy. The base class Velivolo, from Velivolo derive Militare and Civile, from militare derive Aereo and Elicottero, from Civile derive Passeggero e Merce. In every class I have implemented the overload of << and >>. In a class Simulator (not in hierachy) I have implemented...
22
1591
by: maadhuu | last post by:
#include<stdio.h> #include<conio.h> #include<string.h> main() { char * a= "bcd"; clrscr(); strcpy(a,"hello"); a = "fgh"; a = 't';
6
1358
by: Chua Wen Ching | last post by:
Hi there, I have some questions to ask... just say i have this xml file: Scenario :- Script.xml ======== <software> <settings>
1
2496
by: Chris Leffer | last post by:
Hi. Reading some Microsoft materials about asp.net I came into two doubts. The following sentence is found on the topic "Application State" in the NET Framework documentation: "Calling Lock on the Application object causes ASP.NET to block attempts by code running on other worker threads to access anything in application state"
1
1179
by: NagaKiran | last post by:
Hi I want to post VBA related doubts. Where can I post my doubts in VBA? thanks bye
7
1973
by: ramasubramanian.rahul | last post by:
hi i was trying to see how the compiler hides the static golbals from the linker and allows golbal varibale to be visable to the linker.i managed to figure out how it did that ( the .lcomm and .comm sections) but the assembly code for the c program raised a few more doubts . i am enclosing the .c and the .s files .. if someonce could expain...
1
1214
by: CopZ | last post by:
have some doubts regarding the installation of the site $config - This sets the address of your database server. On most installations the database server is located on the same computer as the web server, in which case the address should be set to 'localhost', otherwise use the address of the database server as supplied by your web host. ...
1
1775
by: ramasubramanian.rahul | last post by:
hi people.. dont know if this the right forum for this doubt ... so sorry if i am mis-posting... i was looking at the way glib 2.10.3 does export optimization using a list of "to be exposed" function names in a file caleed glib.symbols. this file is used by a perl script to generate a header a .c file ( galias.h and galiasdefs.c). This...
11
2277
by: destination | last post by:
struct X { int x,y; char c; }; main() { struct X x,*px; px=&x;
0
7521
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7451
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
7720
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7959
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
7810
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
3501
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3483
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
1944
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1061
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.