print ("Help.....\nPlease.....? :3")

B

blackneos940

Guest
So anyway, I found this snippet of Code on dreamincode..... It deals with finding out the Printer on Windows..... Now, I prefer Linux, and, if my Chromebook Charger were working, or if my Inspiron weren't so big and clunky, I could use Linux, even while relaxing..... :) But, if I am going to be in Security, and if I use an OS at ALL, I should know some things about it..... Right.....? :) Nevertheless, this seems to be mostly universal..... Oh, here's the Code...... :3
Code:
#include <Windows.h>
#include <stdio.h>
#pragma comment(lib,"Winspool.lib")

int main()

{
    char input;
    unsigned int i = 0;
    DWORD bufferSize=0;
    BOOL result = FALSE;
    result = GetDefaultPrinter(NULL,&bufferSize); // get size of buffer
    char* printerName = (char*) malloc(sizeof(char)*bufferSize);
    result = GetDefaultPrinter(printerName,&bufferSize); //set size of buffer and get Printer Name
 
    if(result!=0)
      printf("Default Printer is %s\n",printerName);
    else
      printf("Error: Default Printer not returned\n");

    scanf(&input);//used to hold window open replace as you see fit
    free(printerName);
    return 0;
}

What's a "Buffer"......? I think it's a number of Characters..... :\ Hence the use of "char"..... :) Amiright.....? :) Also, why use an Asterisk after char, and before the Variable bufferSize.....? : ( I know that "malloc" means Memory Allocation, but what does "sizeof" mean.....? Also, can you return ANY number in C.....? :) Thank you SO much for the help, you guys..... :D I'm sure the answers will help anyone who is wondering some of the same things..... :) Kthxbai!!..... :3 *He suddenly vanishes from linux.org, off to DOS his Surface RT....... Despite his best efforts, Arochester can't find blackneos940's Account on his Server. It has vanished. But it WILL return.....*..... :3
 


First of all, this piece of badly written code is Windows specific. It has no relationship to how things are done in Linux.

Secondly, to fully understand this code you really need to learn all of the C Programming language from the start, and if so, you would not need to ask the questions. I will however give you some short answers to your questions.
What's a "Buffer"......? I think it's a number of Characters..... :\ Hence the use of "char"..... :) Amiright.....?
A buffer is an area of memory to store any kind of data, in this case, an area of chars big enough to hold the printer name.
Code:
char* printerName = (char*) malloc(sizeof(char)*bufferSize);
Also, why use an Asterisk after char, and before the Variable bufferSize.....? : ( I know that "malloc" means Memory Allocation, but what does "sizeof" mean.....?
This line allocates an area of memory in an area known as the "Heap", memory assigned to the program, but some or all not in use. malloc() takes a number of bytes to allocate.

"sizeof(char)" should not be used here. A char in any implementation of Standard C is 1 (One) and only 1 byte. sizeof() any data type returns the number of bytes that data type takes up in memory. sizeof(int) would return 4 or 8 in modern systems, and 2 in older 16 bit DOS computers. sizeof() can also be used to obtain the size of a data variable, or array.

So the remainder of the call to malloc is (1 * bufferSize) or just bufferSize, whatever value it contains.

malloc() attempts to allocate the area of memory requested and if it can it returns the address of that chunk of memory that is being assigned to the character pointer, printerName. The cast, "(char*) in front of malloc() should not be used. malloc() that adheres to the C Standard should return a generic address (void *) that can be assigned to any pointer without the need of a "Cast".

Again, you really need to thoroughly learn C before diving into code you find on the net. The same is true of any programming language.

I can't speak French. I would not attempt to read a book written in French unless I have taken at least one course, and probably more! ;^)
 
First of all, this piece of badly written code is Windows specific. It has no relationship to how things are done in Linux.

Secondly, to fully understand this code you really need to learn all of the C Programming language from the start, and if so, you would not need to ask the questions. I will however give you some short answers to your questions.
A buffer is an area of memory to store any kind of data, in this case, an area of chars big enough to hold the printer name.
Code:
char* printerName = (char*) malloc(sizeof(char)*bufferSize);

This line allocates an area of memory in an area known as the "Heap", memory assigned to the program, but some or all not in use. malloc() takes a number of bytes to allocate.

"sizeof(char)" should not be used here. A char in any implementation of Standard C is 1 (One) and only 1 byte. sizeof() any data type returns the number of bytes that data type takes up in memory. sizeof(int) would return 4 or 8 in modern systems, and 2 in older 16 bit DOS computers. sizeof() can also be used to obtain the size of a data variable, or array.

So the remainder of the call to malloc is (1 * bufferSize) or just bufferSize, whatever value it contains.

malloc() attempts to allocate the area of memory requested and if it can it returns the address of that chunk of memory that is being assigned to the character pointer, printerName. The cast, "(char*) in front of malloc() should not be used. malloc() that adheres to the C Standard should return a generic address (void *) that can be assigned to any pointer without the need of a "Cast".

Again, you really need to thoroughly learn C before diving into code you find on the net. The same is true of any programming language.

I can't speak French. I would not attempt to read a book written in French unless I have taken at least one course, and probably more! ;^)
Thank you for the help, good sir!..... :3 It helped to clear some things up...... :) But, in all honesty, I had hoped to learn more about C by studying Code..... :D Maybe I..... Need more of a foundation.....? :)
 
But, in all honesty, I had hoped to learn more about C by studying Code....
Sorry, but that just doesn't work for many reasons.
Maybe I..... Need more of a foundation.....?
Yes, by either taking a course from a qualified instructor, or by a good book, studying each chapter front to back, answering the questions at the end of each chapter, and doing the exercises. There are no good shortcuts to learning a computer programming language! There are just too much information to learn in every language!

I used to teach the intro course in C at NYU, 10 or 12 classes, 3 hours each, and then the students went on to learn advanced topics with another instructor for another 10 or 12 weeks! Yes, there is that much information to learn in C.

Not trying to discourage you! Just the opposite! I want you to get a through knowledge of the language! The same for anyone else reading this! I wish I lived closer, I would teach you myself!

There are two books I would recommend. Neither one is perfect, not organized the way I teach, and not quite as thorough as my course, but better than other books. Check the web and eBay for the best price on the book. Choose one only.

C Programming, A Modern Approach, K.N. King Author
Covers the C89 and C99 Standards, but not C11

C Primer Plus, 6th Edition, Stephen Prata Author

I do wish you the best!
 
Sorry, but that just doesn't work for many reasons.Yes, by either taking a course from a qualified instructor, or by a good book, studying each chapter front to back, answering the questions at the end of each chapter, and doing the exercises. There are no good shortcuts to learning a computer programming language! There are just too much information to learn in every language!

I used to teach the intro course in C at NYU, 10 or 12 classes, 3 hours each, and then the students went on to learn advanced topics with another instructor for another 10 or 12 weeks! Yes, there is that much information to learn in C.

Not trying to discourage you! Just the opposite! I want you to get a through knowledge of the language! The same for anyone else reading this! I wish I lived closer, I would teach you myself!

There are two books I would recommend. Neither one is perfect, not organized the way I teach, and not quite as thorough as my course, but better than other books. Check the web and eBay for the best price on the book. Choose one only.

C Programming, A Modern Approach, K.N. King Author
Covers the C89 and C99 Standards, but not C11

C Primer Plus, 6th Edition, Stephen Prata Author

I do wish you the best!


'K!..... :D I'll look into them!!..... ^^ Also, don't worry..... I'm not discouraged!.... ^^ But yeah, having someone nearby to talk to about this stuff, in PERSON, would be a Godsend..... :) I like talkin' to you guys and stuff, and it HELPS, but..... There's just something that can NEVER be emulated by learning through this Series of Tubes...... :3 That gentle hand to guide you, to coach you..... And slap the crap out of you when you make an undefined reference to "getch"..... :3 Oh, how I wish for that....... :D
 
That gentle hand to guide you, to coach you..... And slap the crap out of you when you make an undefined reference to "getch"..... :3 Oh, how I wish for that....... :D
;^)

You would be a great student! I wish more students understood this! I would be happy help you as best I can long distance.
 
;^)

You would be a great student! I wish more students understood this! I would be happy help you as best I can long distance.
Thanks, good sir!..... :3 It feels good to hear that..... :) Actually, now that you mention it..... Here's just SOME of the Linux Kernel I downloaded (try fitting the entire thing on a Netbook..... :D)..... :) You don't have to go through and explain it all..... :D I just wanna know something....... Why isn't there an instance of "int main(void)"....? : ( Do we not always have to use that every time.....? :3
Code:
/*
* Copyright (C) 2008-2014 Mathieu Desnoyers
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <linux/jhash.h>
#include <linux/list.h>
#include <linux/rcupdate.h>
#include <linux/tracepoint.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/static_key.h>

extern struct tracepoint * const __start___tracepoints_ptrs[];
extern struct tracepoint * const __stop___tracepoints_ptrs[];

/* Set to 1 to enable tracepoint debug output */
static const int tracepoint_debug;

#ifdef CONFIG_MODULES
/*
* Tracepoint module list mutex protects the local module list.
*/
static DEFINE_MUTEX(tracepoint_module_list_mutex);

/* Local list of struct tp_module */
static LIST_HEAD(tracepoint_module_list);
#endif /* CONFIG_MODULES */

/*
* tracepoints_mutex protects the builtin and module tracepoints.
* tracepoints_mutex nests inside tracepoint_module_list_mutex.
*/
static DEFINE_MUTEX(tracepoints_mutex);

/*
* Note about RCU :
* It is used to delay the free of multiple probes array until a quiescent
* state is reached.
*/
struct tp_probes {
    struct rcu_head rcu;
    struct tracepoint_func probes[0];
};

static inline void *allocate_probes(int count)
{
    struct tp_probes *p  = kmalloc(count * sizeof(struct tracepoint_func)
            + sizeof(struct tp_probes), GFP_KERNEL);
    return p == NULL ? NULL : p->probes;
}

static void rcu_free_old_probes(struct rcu_head *head)
{
    kfree(container_of(head, struct tp_probes, rcu));
}

static inline void release_probes(struct tracepoint_func *old)
{
    if (old) {
        struct tp_probes *tp_probes = container_of(old,
            struct tp_probes, probes[0]);
        call_rcu_sched(&tp_probes->rcu, rcu_free_old_probes);
    }
}

static void debug_print_probes(struct tracepoint_func *funcs)
{
    int i;

    if (!tracepoint_debug || !funcs)
        return;

    for (i = 0; funcs[i].func; i++)
        printk(KERN_DEBUG "Probe %d : %p\n", i, funcs[i].func);
}

static struct tracepoint_func *func_add(struct tracepoint_func **funcs,
        struct tracepoint_func *tp_func)
{
    int nr_probes = 0;
    struct tracepoint_func *old, *new;

    if (WARN_ON(!tp_func->func))
        return ERR_PTR(-EINVAL);

    debug_print_probes(*funcs);
    old = *funcs;
    if (old) {
        /* (N -> N+1), (N != 0, 1) probes */
        for (nr_probes = 0; old[nr_probes].func; nr_probes++)
            if (old[nr_probes].func == tp_func->func &&
                old[nr_probes].data == tp_func->data)
                return ERR_PTR(-EEXIST);
    }
    /* + 2 : one for new probe, one for NULL func */
    new = allocate_probes(nr_probes + 2);
    if (new == NULL)
        return ERR_PTR(-ENOMEM);
    if (old)
        memcpy(new, old, nr_probes * sizeof(struct tracepoint_func));
    new[nr_probes] = *tp_func;
    new[nr_probes + 1].func = NULL;
    *funcs = new;
    debug_print_probes(*funcs);
    return old;
}

static void *func_remove(struct tracepoint_func **funcs,
        struct tracepoint_func *tp_func)
{
    int nr_probes = 0, nr_del = 0, i;
    struct tracepoint_func *old, *new;

    old = *funcs;

    if (!old)
        return ERR_PTR(-ENOENT);

    debug_print_probes(*funcs);
    /* (N -> M), (N > 1, M >= 0) probes */
    if (tp_func->func) {
        for (nr_probes = 0; old[nr_probes].func; nr_probes++) {
            if (old[nr_probes].func == tp_func->func &&
                old[nr_probes].data == tp_func->data)
                nr_del++;
        }
    }

    /*
    * If probe is NULL, then nr_probes = nr_del = 0, and then the
    * entire entry will be removed.
    */
    if (nr_probes - nr_del == 0) {
        /* N -> 0, (N > 1) */
        *funcs = NULL;
        debug_print_probes(*funcs);
        return old;
    } else {
        int j = 0;
        /* N -> M, (N > 1, M > 0) */
        /* + 1 for NULL */
        new = allocate_probes(nr_probes - nr_del + 1);
        if (new == NULL)
            return ERR_PTR(-ENOMEM);
        for (i = 0; old[i].func; i++)
            if (old[i].func != tp_func->func
                    || old[i].data != tp_func->data)
                new[j++] = old[i];
        new[nr_probes - nr_del].func = NULL;
        *funcs = new;
    }
    debug_print_probes(*funcs);
    return old;
}

/*
* Add the probe function to a tracepoint.
*/
static int tracepoint_add_func(struct tracepoint *tp,
        struct tracepoint_func *func)
{
    struct tracepoint_func *old, *tp_funcs;

    if (tp->regfunc && !static_key_enabled(&tp->key))
        tp->regfunc();

    tp_funcs = rcu_dereference_protected(tp->funcs,
            lockdep_is_held(&tracepoints_mutex));
    old = func_add(&tp_funcs, func);
    if (IS_ERR(old)) {
        WARN_ON_ONCE(1);
        return PTR_ERR(old);
    }

    /*
    * rcu_assign_pointer has a smp_wmb() which makes sure that the new
    * probe callbacks array is consistent before setting a pointer to it.
    * This array is referenced by __DO_TRACE from
    * include/linux/tracepoints.h. A matching smp_read_barrier_depends()
    * is used.
    */
    rcu_assign_pointer(tp->funcs, tp_funcs);
    if (!static_key_enabled(&tp->key))
        static_key_slow_inc(&tp->key);
    release_probes(old);
    return 0;
}

/*
* Remove a probe function from a tracepoint.
* Note: only waiting an RCU period after setting elem->call to the empty
* function insures that the original callback is not used anymore. This insured
* by preempt_disable around the call site.
*/
static int tracepoint_remove_func(struct tracepoint *tp,
        struct tracepoint_func *func)
{
    struct tracepoint_func *old, *tp_funcs;

    tp_funcs = rcu_dereference_protected(tp->funcs,
            lockdep_is_held(&tracepoints_mutex));
    old = func_remove(&tp_funcs, func);
    if (IS_ERR(old)) {
        WARN_ON_ONCE(1);
        return PTR_ERR(old);
    }

    if (!tp_funcs) {
        /* Removed last function */
        if (tp->unregfunc && static_key_enabled(&tp->key))
            tp->unregfunc();

        if (static_key_enabled(&tp->key))
            static_key_slow_dec(&tp->key);
    }
    rcu_assign_pointer(tp->funcs, tp_funcs);
    release_probes(old);
    return 0;
}

/**
* tracepoint_probe_register -  Connect a probe to a tracepoint
* @tp: tracepoint
* @probe: probe handler
* @data: tracepoint data
*
* Returns 0 if ok, error value on error.
* Note: if @tp is within a module, the caller is responsible for
* unregistering the probe before the module is gone. This can be
* performed either with a tracepoint module going notifier, or from
* within module exit functions.
*/
int tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data)
{
    struct tracepoint_func tp_func;
    int ret;

    mutex_lock(&tracepoints_mutex);
    tp_func.func = probe;
    tp_func.data = data;
    ret = tracepoint_add_func(tp, &tp_func);
    mutex_unlock(&tracepoints_mutex);
    return ret;
}
EXPORT_SYMBOL_GPL(tracepoint_probe_register);

/**
* tracepoint_probe_unregister -  Disconnect a probe from a tracepoint
* @tp: tracepoint
* @probe: probe function pointer
* @data: tracepoint data
*
* Returns 0 if ok, error value on error.
*/
int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data)
{
    struct tracepoint_func tp_func;
    int ret;

    mutex_lock(&tracepoints_mutex);
    tp_func.func = probe;
    tp_func.data = data;
    ret = tracepoint_remove_func(tp, &tp_func);
    mutex_unlock(&tracepoints_mutex);
    return ret;
}
EXPORT_SYMBOL_GPL(tracepoint_probe_unregister);

#ifdef CONFIG_MODULES
bool trace_module_has_bad_taint(struct module *mod)
{
    return mod->taints & ~((1 << TAINT_OOT_MODULE) | (1 << TAINT_CRAP) |
                  (1 << TAINT_UNSIGNED_MODULE));
}

static BLOCKING_NOTIFIER_HEAD(tracepoint_notify_list);

/**
* register_tracepoint_notifier - register tracepoint coming/going notifier
* @nb: notifier block
*
* Notifiers registered with this function are called on module
* coming/going with the tracepoint_module_list_mutex held.
* The notifier block callback should expect a "struct tp_module" data
* pointer.
*/
int register_tracepoint_module_notifier(struct notifier_block *nb)
{
    struct tp_module *tp_mod;
    int ret;

    mutex_lock(&tracepoint_module_list_mutex);
    ret = blocking_notifier_chain_register(&tracepoint_notify_list, nb);
    if (ret)
        goto end;
    list_for_each_entry(tp_mod, &tracepoint_module_list, list)
        (void) nb->notifier_call(nb, MODULE_STATE_COMING, tp_mod);
end:
    mutex_unlock(&tracepoint_module_list_mutex);
    return ret;
}
EXPORT_SYMBOL_GPL(register_tracepoint_module_notifier);

/**
* unregister_tracepoint_notifier - unregister tracepoint coming/going notifier
* @nb: notifier block
*
* The notifier block callback should expect a "struct tp_module" data
* pointer.
*/
int unregister_tracepoint_module_notifier(struct notifier_block *nb)
{
    struct tp_module *tp_mod;
    int ret;

    mutex_lock(&tracepoint_module_list_mutex);
    ret = blocking_notifier_chain_unregister(&tracepoint_notify_list, nb);
    if (ret)
        goto end;
    list_for_each_entry(tp_mod, &tracepoint_module_list, list)
        (void) nb->notifier_call(nb, MODULE_STATE_GOING, tp_mod);
end:
    mutex_unlock(&tracepoint_module_list_mutex);
    return ret;

}
EXPORT_SYMBOL_GPL(unregister_tracepoint_module_notifier);

/*
* Ensure the tracer unregistered the module's probes before the module
* teardown is performed. Prevents leaks of probe and data pointers.
*/
static void tp_module_going_check_quiescent(struct tracepoint * const *begin,
        struct tracepoint * const *end)
{
    struct tracepoint * const *iter;

    if (!begin)
        return;
    for (iter = begin; iter < end; iter++)
        WARN_ON_ONCE((*iter)->funcs);
}

static int tracepoint_module_coming(struct module *mod)
{
    struct tp_module *tp_mod;
    int ret = 0;

    if (!mod->num_tracepoints)
        return 0;

    /*
    * We skip modules that taint the kernel, especially those with different
    * module headers (for forced load), to make sure we don't cause a crash.
    * Staging, out-of-tree, and unsigned GPL modules are fine.
    */
    if (trace_module_has_bad_taint(mod))
        return 0;
    mutex_lock(&tracepoint_module_list_mutex);
    tp_mod = kmalloc(sizeof(struct tp_module), GFP_KERNEL);
    if (!tp_mod) {
        ret = -ENOMEM;
        goto end;
    }
    tp_mod->mod = mod;
    list_add_tail(&tp_mod->list, &tracepoint_module_list);
    blocking_notifier_call_chain(&tracepoint_notify_list,
            MODULE_STATE_COMING, tp_mod);
end:
    mutex_unlock(&tracepoint_module_list_mutex);
    return ret;
}

static void tracepoint_module_going(struct module *mod)
{
    struct tp_module *tp_mod;

    if (!mod->num_tracepoints)
        return;

    mutex_lock(&tracepoint_module_list_mutex);
    list_for_each_entry(tp_mod, &tracepoint_module_list, list) {
        if (tp_mod->mod == mod) {
            blocking_notifier_call_chain(&tracepoint_notify_list,
                    MODULE_STATE_GOING, tp_mod);
            list_del(&tp_mod->list);
            kfree(tp_mod);
            /*
            * Called the going notifier before checking for
            * quiescence.
            */
            tp_module_going_check_quiescent(mod->tracepoints_ptrs,
                mod->tracepoints_ptrs + mod->num_tracepoints);
            break;
        }
    }
    /*
    * In the case of modules that were tainted at "coming", we'll simply
    * walk through the list without finding it. We cannot use the "tainted"
    * flag on "going", in case a module taints the kernel only after being
    * loaded.
    */
    mutex_unlock(&tracepoint_module_list_mutex);
}

static int tracepoint_module_notify(struct notifier_block *self,
        unsigned long val, void *data)
{
    struct module *mod = data;
    int ret = 0;

    switch (val) {
    case MODULE_STATE_COMING:
        ret = tracepoint_module_coming(mod);
        break;
    case MODULE_STATE_LIVE:
        break;
    case MODULE_STATE_GOING:
        tracepoint_module_going(mod);
        break;
    case MODULE_STATE_UNFORMED:
        break;
    }
    return ret;
}

static struct notifier_block tracepoint_module_nb = {
    .notifier_call = tracepoint_module_notify,
    .priority = 0,
};

static __init int init_tracepoints(void)
{
    int ret;

    ret = register_module_notifier(&tracepoint_module_nb);
    if (ret)
        pr_warning("Failed to register tracepoint module enter notifier\n");

    return ret;
}
__initcall(init_tracepoints);
#endif /* CONFIG_MODULES */

static void for_each_tracepoint_range(struct tracepoint * const *begin,
        struct tracepoint * const *end,
        void (*fct)(struct tracepoint *tp, void *priv),
        void *priv)
{
    struct tracepoint * const *iter;

    if (!begin)
        return;
    for (iter = begin; iter < end; iter++)
        fct(*iter, priv);
}

/**
* for_each_kernel_tracepoint - iteration on all kernel tracepoints
* @fct: callback
* @priv: private data
*/
void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv),
        void *priv)
{
    for_each_tracepoint_range(__start___tracepoints_ptrs,
        __stop___tracepoints_ptrs, fct, priv);
}
EXPORT_SYMBOL_GPL(for_each_kernel_tracepoint);

#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS

/* NB: reg/unreg are called while guarded with the tracepoints_mutex */
static int sys_tracepoint_refcount;

void syscall_regfunc(void)
{
    struct task_struct *p, *t;

    if (!sys_tracepoint_refcount) {
        read_lock(&tasklist_lock);
        for_each_process_thread(p, t) {
            set_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
        }
        read_unlock(&tasklist_lock);
    }
    sys_tracepoint_refcount++;
}

void syscall_unregfunc(void)
{
    struct task_struct *p, *t;

    sys_tracepoint_refcount--;
    if (!sys_tracepoint_refcount) {
        read_lock(&tasklist_lock);
        for_each_process_thread(p, t) {
            clear_tsk_thread_flag(t, TIF_SYSCALL_TRACEPOINT);
        }
        read_unlock(&tasklist_lock);
    }
}
#endif
 
Take the most famous C program that was ever written, revised for Standard C:
Code:
#include <stdio.h>
int main(void)
{
  printf("Hello World!\n");
  return 0;
}
With the exception to the text,
Hello World!\n
This code will be found in most every C program most programmers will ever write. There are two valid alternatives to the parameter list for main, to allow for command line arguments,
Code:
int main(int argc, char *argv[])
or
int main(int argc, char **argv)
Both of these are basically equivalent. I would need to teach you arrays, pointers, functions, and character strings, to fully understand why! ;^)

There are also other exceptions to writing C code and compiling into a file without a main() function. One of them is the Linux kernel. The boot loader, which would have a main(), will load the kernel. You can read more about the "Linux Startup Process".

Reading the Linux Kernel is NOT for the faint of heart! ;^) It is probably the most complex piece of Linux code. There is a lot in the code that would confuse most programmers!

I don't do kernel programming, and have not viewed the code to any extent, so I can't comment too much on the details, beyond the C language itself.

If you want to read some well written C code, I would suggest looking at source code for the GNU system Coreutils, in the directory for the source code.

Enjoy!
 
Take the most famous C program that was ever written, revised for Standard C:
Code:
#include <stdio.h>
int main(void)
{
  printf("Hello World!\n");
  return 0;
}
With the exception to the text,
This code will be found in most every C program most programmers will ever write. There are two valid alternatives to the parameter list for main, to allow for command line arguments,
Code:
int main(int argc, char *argv[])
or
int main(int argc, char **argv)
Both of these are basically equivalent. I would need to teach you arrays, pointers, functions, and character strings, to fully understand why! ;^)

There are also other exceptions to writing C code and compiling into a file without a main() function. One of them is the Linux kernel. The boot loader, which would have a main(), will load the kernel. You can read more about the "Linux Startup Process".

Reading the Linux Kernel is NOT for the faint of heart! ;^) It is probably the most complex piece of Linux code. There is a lot in the code that would confuse most programmers!

I don't do kernel programming, and have not viewed the code to any extent, so I can't comment too much on the details, beyond the C language itself.

If you want to read some well written C code, I would suggest looking at source code for the GNU system Coreutils, in the directory for the source code.

Enjoy!
So..... There's TWO ways of doing that Command Line argument thingy.....? Can I just choose one.....? :3 Also, thanks for the Links, Mister Penguin!..... ^^ Also, I know I'm just a Green Horn, but I can TRY to read the Kernel, if out of nothing more than curiosity.....? Right....? :D
 
So..... There's TWO ways of doing that Command Line argument thingy.....? Can I just choose one.....? :3 Also, thanks for the Links, Mister Penguin!..... ^^ Also, I know I'm just a Green Horn, but I can TRY to read the Kernel, if out of nothing more than curiosity.....? Right....? :D
When someone is learning C for the first time, instructors and books give assignments for code that don't need "command line arguments". It simplifies the program and lets them concentrate on the topics being taught, until the student has fully learned, functions, arrays, pointers, and character strings, all of which you need to fully understand BEFORE attempting to use C.L.A.! Pointing out the three ways of defining main() is something that I show in the first class, but then only use the Non-CLA version for most of the course. In learning C, you should do the same.

Yes, when you are ready, you do need to choose one of the two equivalent CLA versions. I do recommend
Code:
int main(int argc, char *argv[])
as it better represents how CLA's are laid out in memory, especially for beginners.

Yes, of course you can read the kernel, but as I said, it is very complex written by genius level programmers and use things like "goto" which I would normally recommend avoiding like the plague, as it can easily result in "Spaghetti Code".

In the kernel, however, they use it to tweak the compiler into creating slightly more efficient code. It is used only where needed, and does NOT produce Spaghetti code! A beginner reading the kernel code might be easily mislead that the use of "goto" is OK, when in most cases, it should be avoided, even if it produces slightly less efficient code. A modern multi-core 64 bit computer, can execute code so fast, slightly "less efficient" code has little effect on the program. A profiler can be used to determine where the code can and does need to be improved.

I'm sure. other examples exist of code in the kernel that could and probably does confuse beginners.

Downloading and examining the source code for the GNU coreutils, lets you examine the source code for many of the utilities that you use everyday in Linux. You know how they work, now see how they are written. These individual small utilities will give you a better understanding of C than the kernel code will.

Again, you will get am even better understanding of the language by studying one of the books I have suggested earlier, BEFORE studying Coreutils, or Linux kernel code.
 
When someone is learning C for the first time, instructors and books give assignments for code that don't need "command line arguments". It simplifies the program and lets them concentrate on the topics being taught, until the student has fully learned, functions, arrays, pointers, and character strings, all of which you need to fully understand BEFORE attempting to use C.L.A.! Pointing out the three ways of defining main() is something that I show in the first class, but then only use the Non-CLA version for most of the course. In learning C, you should do the same.

Yes, when you are ready, you do need to choose one of the two equivalent CLA versions. I do recommend
Code:
int main(int argc, char *argv[])
as it better represents how CLA's are laid out in memory, especially for beginners.

Yes, of course you can read the kernel, but as I said, it is very complex written by genius level programmers and use things like "goto" which I would normally recommend avoiding like the plague, as it can easily result in "Spaghetti Code".

In the kernel, however, they use it to tweak the compiler into creating slightly more efficient code. It is used only where needed, and does NOT produce Spaghetti code! A beginner reading the kernel code might be easily mislead that the use of "goto" is OK, when in most cases, it should be avoided, even if it produces slightly less efficient code. A modern multi-core 64 bit computer, can execute code so fast, slightly "less efficient" code has little effect on the program. A profiler can be used to determine where the code can and does need to be improved.

I'm sure. other examples exist of code in the kernel that could and probably does confuse beginners.

Downloading and examining the source code for the GNU coreutils, lets you examine the source code for many of the utilities that you use everyday in Linux. You know how they work, now see how they are written. These individual small utilities will give you a better understanding of C than the kernel code will.

Again, you will get am even better understanding of the language by studying one of the books I have suggested earlier, BEFORE studying Coreutils, or Linux kernel code.

Ok, then..... :3 So, for now, I should learn those things FIRST..... :D Got it!.... :3 So there ARE some things goto can be adequately used for..... :) I had thought that it would be a BAD thing to use outright..... :D So, is x64 faster than x32.....? :) Also, I got one of those books..... :D C Primer Plus..... :3 So I've been reading it for a while..... :D It really helps..... :3 Thanks for the recommendation, Good Penguin Sir!..... ^^ :3
 
Things to do and not to do can be learned by the C book, other books on Data Structures, Algorithms, and other books you should read and study once you have a good background in C.

"goto", and other, programming "crutches" do have their limited use, but for most programmers they should be avoided by changing the algorithm or splitting a complex function into multiple functions.

Good luck with the studying!

Cheers!
 
Things to do and not to do can be learned by the C book, other books on Data Structures, Algorithms, and other books you should read and study once you have a good background in C.

"goto", and other, programming "crutches" do have their limited use, but for most programmers they should be avoided by changing the algorithm or splitting a complex function into multiple functions.

Good luck with the studying!

Cheers!

Ok, Good Sir!..... :3 So, after getting better at C, I should start to study Data Structures and Algorithms.....? :) I remember watching a Java Course, and the guy said that even though some people watching the course might not be Java Programmers, his take on Algorithms would STILL help others who don't know Java that well..... :D But when you speak of Algorithms, do you refer to a general outline of what the Program will do.....? :) Also, I wonder how many topics there really ARE in C..... I wonder if Linus and Richard are masters at C......? :)
 
There is a lot to learn in an field of programming. A good book on Algorithms, and another on Data Structures, (Or a combination of the two.) or course(s) with a qualified instructor, would be a good followup to a good background in C.
I wonder if Linus and Richard are masters at C......?
I would say yes, considering that the Linux kernel is programmed ONLY in C, and the majority of the code in the GNU system, the FSF has added to the kernel to create the base for what we call, Linux, or GNU/Linux. Without examining all the other packages available for Linux, I would also guess that C and C++ would be the primary languages in most of the source code. No, I don't have a reference to any study on the breakdown of languages, although I'm sure one or more were attempted.

Learning doesn't end in this business, as the hardware, O/S's, Languages, applications, utilities, Standards, etc... are in constant creation, change, and improvement (Or sometimes, deterioration)!
 
There is a lot to learn in an field of programming. A good book on Algorithms, and another on Data Structures, (Or a combination of the two.) or course(s) with a qualified instructor, would be a good followup to a good background in C.
I would say yes, considering that the Linux kernel is programmed ONLY in C, and the majority of the code in the GNU system, the FSF has added to the kernel to create the base for what we call, Linux, or GNU/Linux. Without examining all the other packages available for Linux, I would also guess that C and C++ would be the primary languages in most of the source code. No, I don't have a reference to any study on the breakdown of languages, although I'm sure one or more were attempted.

Learning doesn't end in this business, as the hardware, O/S's, Languages, applications, utilities, Standards, etc... are in constant creation, change, and improvement (Or sometimes, deterioration)!
Tiobe_index.png

As you see, C is the most popular language overall. Besides, Linux kernel itself consists of C by 94.6%, of Assembly by 2.6% and some other (from OpenHub).

C++ was actually criticised by some wise men like rms, Linus and Ken Thompson.

Please excuse for going off-topic :D
 
I'm glad to see in this graph that Java is dipping, but sorry it is not nose diving!

I was under the impression that the kernel had NO C++ Code at all. Assembly does not surprise me, only that it is so low in relation to C.
 

Members online


Top