LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
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 08-06-2007, 11:12 AM   #1
rubadub
Member
 
Registered: Jun 2004
Posts: 233

Rep: Reputation: 33
Pointer warnings


Hi,
How to accomplish this please?
Code:
#include <stdio.h>
#include <stdlib.h>

int test(char *(*l[1024]))
{
	char * sa[1024];
	sa[0] = "test";
	sa[1] = "test2";
	sa[2] = "test3";
	
	//l = (char*) malloc(3 * sizeof(char[1024]));
	*l = (char*) calloc(3, sizeof(char[1024]));
	//*l = *sa;
	
	return 0;
}

int main()
{
	char *ll[1024];
	int iret = test(&ll);
	printf("%s \n", ll[0]);
	
	return 0;
}
 
Old 08-06-2007, 12:10 PM   #2
paulsm4
Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
Use the standard C string functions: strcpy, strcmp, strlen, etc..

man strcpy
 
Old 08-06-2007, 12:10 PM   #3
rupertwh
Member
 
Registered: Sep 2006
Location: Munich, Germany
Distribution: Debian / Ubuntu
Posts: 297

Rep: Reputation: 49
Quote:
Originally Posted by rubadub
Code:
	int iret = test(&ll);
The '&' doesn't make sense here, a simple 'test(ll)' will do. 'll' already evaluates to a pointer to the first element of the array. (I.e. a pointer to a pointer to char, 'char**')

With
Quote:
Originally Posted by rubadub
Code:
int test(char *(*l[1024]))
you probably meant
Code:
int test(char *(*l)[1024])
which adds an unnecessary layer of indirection.

Accordingly, a simple
Code:
int test(char **l)
will do. (Instead of 'char **l', You can also write 'char *l[]' or 'char *l[1024]' if it makes you more comfortable, but it doesn't accomplish anything.

Thus simplified, you may rethink your malloc()s: What to you want to malloc for, how much space to you need, how many malloc()s do you need?
 
Old 08-06-2007, 12:17 PM   #4
rubadub
Member
 
Registered: Jun 2004
Posts: 233

Original Poster
Rep: Reputation: 33
That only works for the first element in the array, and doesn't get rid of the warnings...

cheers though

p.s. memcpy doesn't work either, and i'm trying to avoid linked list's for this...
 
Old 08-06-2007, 12:22 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Your use of l as a variable is very confusing. It looks just like a 1 with fixed fonts.

A char * [] is really just a char * const *, which is a const pointer to an array of pointers. You cannot assign a new value to it, which means the value ll "cannot" be changed. I quote "cannot" because char *(*[1024]) is reduced to char***, but it should be char *(*)[1024], which gives the correct compilation error for assigning to a const location.

If you cast &ll to (char***) and change the cast of calloc to (char**) it will compile, but that just happens to be a hole in compilation simplification. That is as bad as trying to do this:
Code:
char mystring[] = "this is data";
mystring[0] = 'T';
Who knows what it will do to your program, but it can't be good.

As I stated before, the correct argument for your function would be char *(*l)[1024]. You won't need to cast &ll then, and rightly you will get an assignment error. What are you trying to get done exactly?
ta0kira

PS The only warnings I get have to do with unused variables. Everything else is error messages.

Last edited by ta0kira; 08-06-2007 at 12:26 PM.
 
Old 08-06-2007, 12:30 PM   #6
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by rubadub
Code:
    char * sa[1024];
    sa[0] = "test";
    sa[1] = "test2";
    sa[2] = "test3";
Unless you create sa as follows, there is a good chance that when sa[1] is assigned sa[0] will no longer be "test".
Code:
const char *sa[1024] = { "test", "test2", "test3", };
This, of course, precludes assigning pointers to the rest of the elements.
ta0kira

Last edited by ta0kira; 08-06-2007 at 12:32 PM.
 
Old 08-06-2007, 12:39 PM   #7
rubadub
Member
 
Registered: Jun 2004
Posts: 233

Original Poster
Rep: Reputation: 33
The assignments are just an placeholder for some kind of loop, e.g. read directory listing.

I'm used to using arrays (vectors in c++) for most things in other languages, had probs with 'dynamic' arrays in c so lately i've been using linked lists, but it just seems overkill, so i've come back to try again.

One thing I can say is that I won't be able to predefine the elements of the array.

hmmm... what i'm wanting is an array of strings 1024 chars long, am I getting frustrated and somewhat confused with my declaration?

...and I thought I used to know c, but before I only really ever dealt with numbers, so...

p.s. v confused today, quitting smoking, arrrgh!
 
Old 08-06-2007, 01:37 PM   #8
rupertwh
Member
 
Registered: Sep 2006
Location: Munich, Germany
Distribution: Debian / Ubuntu
Posts: 297

Rep: Reputation: 49
Quote:
Originally Posted by rubadub
hmmm... what i'm wanting is an array of strings 1024 chars long, am I getting frustrated and somewhat confused with my declaration?
But instead you declared an array of 1024 pointers to char. (That might explain why you thought my suggestion didn't work.)

So what you are looking for is probably a declaration in main() like
Code:
char three_strings[3][1024]; /* an array of 3 arrays of 1024 chars */
and a function definition like
Code:
int test(char (*a)[1024])  /* or  char a[][1024]  */
{
    strcpy(a[0], "bla");
    ...
Which you would call as
Code:
 test(three_strings); /* no need for an & */
.
 
Old 08-06-2007, 01:53 PM   #9
rubadub
Member
 
Registered: Jun 2004
Posts: 233

Original Poster
Rep: Reputation: 33
No, I was replying to paulsm, there was only one post at time... (I should use quote!)
Quote:
(That might explain why you thought my suggestion didn't work.)
Right, this is the new version, do I need some form of malloc, either way i'm getting seg faults.
Oh and I won't know how many elements will be returned so it needs to variable.

Code:
int test2(char (*a)[1024])
{
	char * sa[1024];
	sa[0] = "test";
	sa[1] = "test2";
	sa[2] = "test3";
	
	//*a[0] = (char*) malloc(1024*sizeof(char));
	strcpy(a[0], sa[0]);
	
	return 0;
}

int main()
{
	char (*a)[1024];
	int iret = test2(a);
	printf("%s \n", a[0]);
	printf("%s \n", a[1]);
	printf("%s \n", a[2]);
	
	return 0;
}
I'm really feeling stuppered (stupid & scuppered)

Last edited by rubadub; 08-06-2007 at 02:15 PM.
 
Old 08-06-2007, 02:24 PM   #10
rupertwh
Member
 
Registered: Sep 2006
Location: Munich, Germany
Distribution: Debian / Ubuntu
Posts: 297

Rep: Reputation: 49
Hi rubadub,

inside main(), you declared 'a' as a pointer to an array of 1024 chars, but nowhere has memory been assigned to it.
So either -- if you know the number of strings beforehand -- you can declare 'a' as e.g. 'char a[3][1024]' which would give you three strings of length 1024,
or you will have to use malloc() to reserve memory for your strings.

inside test2(), you declared 'sa' as an array of 1024 pointers to char. Perfectly legal, but probably not what you wanted. Then to the first three of those 1024 pointers you assign your three strings. Again, perfectly legal, even though it probably does not do what you think it does. (But it will work in this situation and is not causing your segfault)

Code:
strcpy(a[0], sa[0]);
Here you are finally writing to a random memory location. (because there is no memory assigned to 'a', see above)

You really need to get a good book on pointers in C. Unfortunately the only truly good book on this topic that I know of has been out of print for a while (A. Holub's "C Companion"). But you do at least have K&R's "The C Programming Language", I hope?

Last edited by rupertwh; 08-06-2007 at 02:26 PM.
 
Old 08-06-2007, 02:34 PM   #11
rubadub
Member
 
Registered: Jun 2004
Posts: 233

Original Poster
Rep: Reputation: 33
Yeah i'd buy Mr Ritchies book if I had any cash, and most examples of pointer use is basic and generally use numbers not strings. And I presume I should also look elsewhere for answers, not that i'm being rude or presumptuous, but too many suggestions and no real answers, oh yes I do actually mean an example. But i'm not going to beg...
 
Old 08-06-2007, 02:41 PM   #12
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Here is how I would do it:
Code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>


int load_name(char *(lList)[1024], const char *sString)
{
    char **current = lList,
         **final   = current + 1024;

    while (current < final)
    if (!*current) return (*current = strdup(sString)) != 0x00;
    else ++current;

    return 0;
}


void show_names(char *(lList)[1024])
{
    char **current = lList,
         **final   = current + 1024;

    while (current < final)
    {
    if (*current) printf("%i:\t%s\n", 1024 - (final - current), *current);
    ++current;
    }
}


void free_name(char **sString)
{
    if (sString) free(*sString);
    if (sString) *sString = 0x00;
}


void free_names(char *(lList)[1024])
{
    char **current = lList,
         **final   = current + 1024;

    while (current < final) free_name(current++);
}


int main()
{
    char *string_list[1024];

    int I; for (I = 0; I < 1024; I++) string_list[I] = 0x00;

    load_name(string_list, "data 0");
    load_name(string_list, "data 1");
    load_name(string_list, "data 2");

    show_names(string_list);

    free_name(string_list + 1);
    load_name(string_list, "changed data 1");

    show_names(string_list);

    free_names(string_list);

}
I'm sorry, I haven't been able to run this because I'm at work, but it compiles.

If you need a dynamic number of strings, I would go with a linked list. They are easier to implement than you think.
ta0kira

Last edited by ta0kira; 08-06-2007 at 03:48 PM. Reason: fixed code so it works!
 
Old 08-06-2007, 06:39 PM   #13
rupertwh
Member
 
Registered: Sep 2006
Location: Munich, Germany
Distribution: Debian / Ubuntu
Posts: 297

Rep: Reputation: 49
Quote:
Originally Posted by rubadub
Yeah i'd buy Mr Ritchies book if I had any cash, and most examples of pointer use is basic and generally use numbers not strings. And I presume I should also look elsewhere for answers, not that i'm being rude or presumptuous, but too many suggestions and no real answers, oh yes I do actually mean an example. But i'm not going to beg...
Here you go

Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define STRSIZE 1024

void test(char a[][STRSIZE], size_t num);

int main(void)
{
        char strs[5][STRSIZE];
        int i;

        printf("sizes:\n\tstrs: %lu\n\tstrs[0]: %lu\n\tstrs[0][0]: %lu\n\n",
                sizeof strs, sizeof strs[0], sizeof strs[0][0]);

        memset(strs, 0, sizeof strs);

        test(strs, sizeof strs / sizeof strs[0]);

        for (i = 0; i < sizeof strs / sizeof strs[0]; i++) 
                printf("%d: %s\n", i, strs[i]);

        return 0;
}

void test(char a[][STRSIZE], size_t num)
{
        /* note that 'a' here isn't actually an array, but rather
         * a pointer to a char array of size STRSIZE
         * which is why you might as well use char (*a)[STRSIZE]. */

        printf("sizes:\n\ta: %lu\n\ta[0]: %lu\n\ta[0][0]: %lu\n\n",
                sizeof a, sizeof a[0], sizeof a[0][0]);


        if (num < 3) {
                puts("Array too small!");
                return;
        }

        strcpy(a[0], "one");
        strcpy(a[1], "two");
        strcpy(a[2], "three");
}
 
Old 08-06-2007, 07:46 PM   #14
rubadub
Member
 
Registered: Jun 2004
Posts: 233

Original Poster
Rep: Reputation: 33
Thankyou both for your time and effort. Akira achieves the green line, yet use's a list (albeit i've only done with structures before, not just pointers, if I comprehend correctly). However Rupert, what you've done is static, not dynamic, which was the point of this exercise.

It's been a few years since i've used c, coming back from using python with a bout of php. From scouring the laney of the internet it does suggest that lists are used for this problem. So I suppose i'll digress and pass excuses for bein a bit o' a Hiro Protagonist with a few stigmata!

It's a funny ol' life, have fun!

Cheers
 
Old 08-06-2007, 09:39 PM   #15
rupertwh
Member
 
Registered: Sep 2006
Location: Munich, Germany
Distribution: Debian / Ubuntu
Posts: 297

Rep: Reputation: 49
Well, you have been sufficiently unclear about what your question is. Are you actually just asking how to dynamically allocate an array of fixed-length strings? As in
Code:
int numstrings;
char (*a)[1024];

...
a = malloc(numstrings * sizeof *a);

strcpy(a[0], "bla1");
strcpy(a[1], "bla2");
...
You should choose a linked list if it is more efficient for the purpose, be in terms of program speed or code readability. But there sure is nothing that could only be done with a linked list in C.
 
  


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
About pointer signedness warnings isuck@linux Linux - Software 2 08-26-2006 08:18 PM
pass pointer,, return pointer??? blizunt7 Programming 3 07-23-2005 02:36 PM
returning data to main() via a pointer to a pointer. slzckboy Programming 3 05-30-2005 02:20 PM
hot to set value of pointer to pointer to a structure in C alix123 Programming 2 11-17-2004 07:40 AM
How does one surpress incompatible pointer type warnings? tonyfreeman Programming 1 08-18-2004 07:06 PM


All times are GMT -5. The time now is 01:14 AM.

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