LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   Pointer warnings (http://www.linuxquestions.org/questions/programming-9/pointer-warnings-575098/)

rubadub 08-06-2007 11:12 AM

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;
}


paulsm4 08-06-2007 12:10 PM

Use the standard C string functions: strcpy, strcmp, strlen, etc..
 
man strcpy

rupertwh 08-06-2007 12:10 PM

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?

rubadub 08-06-2007 12:17 PM

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...

ta0kira 08-06-2007 12:22 PM

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.

ta0kira 08-06-2007 12:30 PM

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

rubadub 08-06-2007 12:39 PM

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!

rupertwh 08-06-2007 01:37 PM

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 & */
.

rubadub 08-06-2007 01:53 PM

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)

rupertwh 08-06-2007 02:24 PM

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?

rubadub 08-06-2007 02:34 PM

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...:Pengy:

ta0kira 08-06-2007 02:41 PM

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

rupertwh 08-06-2007 06:39 PM

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...:Pengy:

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");
}


rubadub 08-06-2007 07:46 PM

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

rupertwh 08-06-2007 09:39 PM

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.


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