LinuxQuestions.org
Visit Jeremy's Blog.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 07-17-2004, 02:02 AM   #1
veritas
Member
 
Registered: Aug 2003
Location: Dallas,TX
Distribution: Ubuntu Server, Slackware, Red Hat 6.1
Posts: 241

Rep: Reputation: 30
a question about array pointers in C


Lately I've been following a tutorial on the C program language. Most of its been a breeze but I'm stuck on this one part about pointers dealing with arrays. Here's the code:
Code:
int add_array(int array[], int size)
{      
        int i;
        int total = 0;

        for(i = 0; i < size; i++)
                total += array[i];

        return(total);
}
I understand the everything except the function declaration, int add_array(int array[], int size). I just don't understand the point of "int array[]" other than it has something to do with a pointer. When I create a main function and call "add_array(10,10)" I get a warning saying "passing arg 1 of 'add_array' makes pointer from integer without cast". (and a segment fault when the program is executed)What is a cast and what exactly are you supposed to put in the first argument slot?
 
Old 07-17-2004, 02:26 AM   #2
osvaldomarques
Member
 
Registered: Jul 2004
Location: Rio de Janeiro - Brazil
Distribution: Conectiva 10 - Conectiva 8 - Slackware 9 - starting with LFS
Posts: 519

Rep: Reputation: 34
Hi veritas,
Your function wants to receive an array pointer as the first argument and you are giving it an integer. In the main function you have to declare an array
Code:
int xyz[10];
then initialize it and then pass it to the function.
Code:
add_array(xyz, 10);
The compile warning told you you are passing an integer "10" in place of an array pointer. So the function tried to use the number 10 as the memory address of your array. As it was out of bounds, you got the seg fault in the execution.
Remember, c will always try to follow your desires or die trying to do it. I always look for every warning and I remove it because, in a "warning forest" we cannot discover the bad ones.

I hope this helps.
 
Old 07-17-2004, 02:53 AM   #3
rgiggs
Member
 
Registered: Apr 2004
Location: berkeley, ca
Distribution: slk10, winxp
Posts: 313

Rep: Reputation: 30
a cast is a way to tell the compiler to interpret something as a different type than it would normally interpret, and to tell it you know exactly what you are doing.
in your case, 10 is normally an integer. that's why the compiler complains when you give add_array an integer when add_array expects an integer pointer. now, if you want to get rid of the warning, you can do add_array((integer *)10, 10), which tells the compiler that you know exactly that the address 10 points to an integer. of course, you will still get the seg fault run time error because the address 10 doesn't belong to you.
 
Old 07-17-2004, 01:20 PM   #4
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
If somehow you knew that 10 was a valid pointer, you'd be able to cast 10 to a pointer to avoid the warning. However, you'd still get the segfault because you'll never see 10 be a valid pointer. To get rid of the warning you'd do add_array((int *)10, 10);
 
Old 07-17-2004, 02:45 PM   #5
veritas
Member
 
Registered: Aug 2003
Location: Dallas,TX
Distribution: Ubuntu Server, Slackware, Red Hat 6.1
Posts: 241

Original Poster
Rep: Reputation: 30
Quote:
Originally posted by osvaldomarques

Code:
int xyz[10];
Ah ok. That helps a lot, mainly because I didn't know I was supposed to declare that in the main function. The tutorial just gave me the add_array function without the main function. Thanks for all of the replys. Now this is making sense.
 
Old 07-17-2004, 02:55 PM   #6
The_Nerd
Member
 
Registered: Aug 2002
Distribution: Debian
Posts: 540

Rep: Reputation: 32
int add_array(int *array, int size)

is basiaclly the same thing. However, it is faster. You see, when the function add_array gets called, the variables array and size are created (on the stack?) and the values that belong to them are assigned to them. So when you have an array, say of 100, then 100 values have to get assigned at each function call! (actually +1 for size). But using pointers, you only ever need one value assigned (+1 for size) because a pointer only holds the value of the start of an array, or the address of an array.

So you have a memory chunk in your computer, like so:
1...2...10 n
---------------------------------------

And when you typecast 10 to a address your function will start assigning values from memory startying at 10. Just put it this way, you'll NEVER see a memory address of 10! So basically, your program is trying to access and/or give itself memory, or maybe something else, that doesn't belong to it. Here is the difference between a intager variable, and an intager array (V is where the value is in memory):

Int Var: (memory) V-----------------
Int Array: (memory) VVVVVVVVVV----

So this would be perfectly valid:

int var=1;

add_array((int *)&var, 1);

However, if you said:

add_array((int *)&var, 2);

You would cause a SEGV because you are trying to access memory beyond the address location where var is stored in memory.


Sum:
int add_array(int array[], int size)

this is the same as the following except that it is way slower and take way more memory:

int add_array(int *array, int size)


Sorry I don't write to well, I hope you understand and get the picture.
 
Old 07-17-2004, 03:13 PM   #7
veritas
Member
 
Registered: Aug 2003
Location: Dallas,TX
Distribution: Ubuntu Server, Slackware, Red Hat 6.1
Posts: 241

Original Poster
Rep: Reputation: 30
Quote:
int add_array(int array[], int size)

this is the same as the following except that it is way slower and take way more memory:

int add_array(int *array, int size)
Thanks. I'll definitely keep that in mind. All though some of the stuff was a bit over my head, but I get the basic picture.
 
Old 07-17-2004, 05:06 PM   #8
osvaldomarques
Member
 
Registered: Jul 2004
Location: Rio de Janeiro - Brazil
Distribution: Conectiva 10 - Conectiva 8 - Slackware 9 - starting with LFS
Posts: 519

Rep: Reputation: 34
Hi veritas,
When there is doubt, the computer always have reason. So, I wrote a little piece of c to check the assembler code produced. Intentionally I left one of the warnings which make the "forest" and its easy to remove. The c source file has 3 identical functions, one with pointer declaration, one with an empty array and one with a full array declaration. All the 3 functions are called from main. I compiled it to generate assembler source instead of generate final code. Here is the test.c source
Code:
int add_full_array(int arr[10], int size)
{
  int ret
     ;
  ret = *arr * size;
  return(ret);
}

int add_array(int arr[], int size)
{
  int ret
     ;
  ret = *arr * size;
  return(ret);
}

int add_pointer(int *ptr, int size)
{
  int ret
     ;
  ret = *ptr * size;
  return(ret);
}

void main(void)
{
  int tst[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
     ;
  int var
     ;
  var = 1;
  add_full_array(tst, 10);
  var = 2;
  add_array(tst, 10);
  var = 3;
  add_pointer(tst, 10);
  var = 4;
}
Here is the resulting test.asm source
Code:
        .file   "test.c"
        .version        "01.01"
gcc2_compiled.:
.text
        .align 4
.globl add_full_array
        .type    add_full_array,@function
add_full_array:
        pushl %ebp
        movl %esp,%ebp
        subl $24,%esp
        movl 8(%ebp),%eax
        movl (%eax),%edx
        imull 12(%ebp),%edx
        movl %edx,-4(%ebp)
        movl -4(%ebp),%edx
        movl %edx,%eax
        jmp .L2
        .p2align 4,,7
.L2:
        leave
        ret
.Lfe1:
        .size    add_full_array,.Lfe1-add_full_array
        .align 4
.globl add_array
        .type    add_array,@function
add_array:
        pushl %ebp
        movl %esp,%ebp
        subl $24,%esp
        movl 8(%ebp),%eax
        movl (%eax),%edx
        imull 12(%ebp),%edx
        movl %edx,-4(%ebp)
        movl -4(%ebp),%edx
        movl %edx,%eax
        jmp .L3
        .p2align 4,,7
.L3:
        leave
        ret
.Lfe2:
        .size    add_array,.Lfe2-add_array
        .align 4
.globl add_pointer
        .type    add_pointer,@function
add_pointer:
        pushl %ebp
        movl %esp,%ebp
        subl $24,%esp
        movl 8(%ebp),%eax
        movl (%eax),%edx
        imull 12(%ebp),%edx
        movl %edx,-4(%ebp)
        movl -4(%ebp),%edx
        movl %edx,%eax
        jmp .L4
        .p2align 4,,7
.L4:
        leave
        ret
.Lfe3:
        .size    add_pointer,.Lfe3-add_pointer
.section        .rodata
        .align 4
.LC0:
        .long 0
        .long 1
        .long 2
        .long 3
        .long 4
        .long 5
        .long 6
        .long 7
        .long 8
        .long 9
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl %ebp
        movl %esp,%ebp
        subl $64,%esp
        pushl %edi
        pushl %esi
        leal -40(%ebp),%edi # get tst array local address
        movl $.LC0,%esi     # get address of initializer
        cld                 # clear direction
        movl $10,%ecx       # set counter to 10 repetitions
        rep                 # start repeat
        movsl               # move string long
        movl $1,-44(%ebp)   # var = 1;
        addl $-8,%esp
        pushl $10
        leal -40(%ebp),%eax
        pushl %eax
        call add_full_array
        addl $16,%esp
        movl $2,-44(%ebp)   # var = 2;
        addl $-8,%esp
        pushl $10
        leal -40(%ebp),%eax
        pushl %eax
        call add_array
        addl $16,%esp
        movl $3,-44(%ebp)   # var = 3;
        addl $-8,%esp
        pushl $10
        leal -40(%ebp),%eax
        pushl %eax
        call add_pointer
        addl $16,%esp
        movl $4,-44(%ebp)   # var = 4;
.L5:
        leal -72(%ebp),%esp
        popl %esi
        popl %edi
        leave
        ret
.Lfe4:
        .size    main,.Lfe4-main
        .ident  "GCC: (GNU) 2.95.3 20010315 (release)"
In the c, on the main function, I introduced a variable called "var", and before each function call I initialized it to ease the tracking of the start and end of the function calls into the resulting assembler. In the resulting assembler, I did some notes after '#' in the main function, showing the array initialization and marking where the var variable is initialized. As we can see, the code of the 3 functions are completely identical and the assembler instructions to call each of the functions are also the same.

That's the part of my life I most hate. When I disagree with the computer, it is always right! By the way, the command used to compile it is
Code:
gcc -S -o test.asm test.c
 
Old 07-17-2004, 05:32 PM   #9
Proud
Senior Member
 
Registered: Dec 2002
Location: England
Distribution: Used to use Mandrake/Mandriva
Posts: 2,794

Rep: Reputation: 116Reputation: 116
Thanks a bunch osvaldomarques, I was thinking the others were slightly incorrect and that reply really explains it all.

Just wanted to check veritas, you were reading this page right?
 
Old 07-17-2004, 05:45 PM   #10
rgiggs
Member
 
Registered: Apr 2004
Location: berkeley, ca
Distribution: slk10, winxp
Posts: 313

Rep: Reputation: 30
phew, The_Nerd scared the hell out of me because I haven't used C in a while and what The_Nerd said was completely different than what I remembered. I thought my C was so rusty. but thanks to osvaldomarques, i didn't have to verify the situation.
 
Old 07-17-2004, 07:26 PM   #11
veritas
Member
 
Registered: Aug 2003
Location: Dallas,TX
Distribution: Ubuntu Server, Slackware, Red Hat 6.1
Posts: 241

Original Poster
Rep: Reputation: 30
Quote:
Just wanted to check veritas, you were reading this page right?
Yep, thats the one. But now I'm reading a pretty thorough pointers tutorial located here:

http://pweb.netcom.com/~tjensen/ptr/pointers.htm

edit: I will continue with the other one when i get a complete grasp on pointers dealing with the most common data types. I wonder why the strath.ac.uk website went into pointers so early (since they deal with memory locations and other non newbie friendly things)? There is probably another way to demonstrate a while loop.

Last edited by veritas; 07-17-2004 at 07:32 PM.
 
Old 07-18-2004, 01:24 PM   #12
llama_meme
Member
 
Registered: Nov 2001
Location: London, England
Distribution: Gentoo, FreeBSD
Posts: 590

Rep: Reputation: 30
Quote:
int add_array(int *array, int size)

is basiaclly the same thing. However, it is faster. You see, when the function add_array gets called, the variables array and size are created (on the stack?) and the values that belong to them are assigned to them. So when you have an array, say of 100, then 100 values have to get assigned at each function call! (actually +1 for size). But using pointers, you only ever need one value assigned (+1 for size) because a pointer only holds the value of the start of an array, or the address of an array.
No, array arguments to functions are passed as pointers; they aren't copied. If you use int array[] instead of int *array as the argument, the only difference is that you could modify the 'array' variable. In general:

int *foo;
and
int foo[];

are exactly the same except for the fact that in the first one, 'foo' is a variable and can have its value changed, whereas in the second, 'foo' is not a variable and its value is fixed.

Alex
 
Old 07-18-2004, 06:31 PM   #13
osvaldomarques
Member
 
Registered: Jul 2004
Location: Rio de Janeiro - Brazil
Distribution: Conectiva 10 - Conectiva 8 - Slackware 9 - starting with LFS
Posts: 519

Rep: Reputation: 34
Hi gentlemen,

Sorry, but gcc disagree with us. I said I hate this, but, I did alter the previous c source to produce some result
Code:
#include <stdio.h>

int add_full_array(int arr[10], int size)
{
  int ret
     ;
  for (ret = 0; size; arr++, size--)
  {
    ret += *arr * size;
//    printf("Processing: ret = %d * %d\n", *arr, size);
  }
  printf("add full array: %d\n", ret);
  return(ret);
}

int add_array(int arr[], int size)
{
  int ret
     ;
  for (ret = 0; size; arr++, size--)
  {
    ret += *arr * size;
//    printf("Processing: ret = %d * %d\n", *arr, size);
  }
  printf("add array:      %d\n", ret);
  return(ret);
}

int add_pointer(int *ptr, int size)
{
  int ret
     ;
  for (ret = 0; size; ptr++, size--)
  {
    ret += *ptr * size;
//    printf("Processing: ret = %d * %d\n", *ptr, size);
  }
  printf("add pointer:    %d\n", ret);
  return(ret);
}

void main(void)
{
  int tst[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
     ;
  int var
     ;
  var = 1;
  add_full_array(tst, 10);
  var = 2;
  add_array(tst, 10);
  var = 3;
  add_pointer(tst, 10);
  var = 4;
}
and compiled it with
Code:
gcc -o test test.c
After run it (./test), the result is
Code:
Opiii:~/teste# ./test
add full array: 165
add array:      165
add pointer:    165
 
  


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
c array of pointers greg108 Programming 10 08-17-2005 10:25 AM
SIGSEGV: Array of character pointers?? usercsr Programming 2 04-23-2005 11:34 AM
array of char pointers djgerbavore Programming 2 01-08-2005 01:59 PM
question about pointers vijeesh_ep Programming 1 09-13-2004 03:13 PM
question on pointers h/w Programming 1 10-26-2003 02:54 PM


All times are GMT -5. The time now is 08:42 PM.

Main Menu
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
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration